Cegah gulir browser otomatis saat menyegarkan

95

Jika Anda membuka halaman a dan menggulirnya, maka segarkan halaman tersebut akan disegarkan di tempat Anda meninggalkannya. Ini bagus, namun ini juga terjadi pada halaman yang memiliki lokasi jangkar di url. Contohnya adalah jika Anda mengklik link http://example.com/post/244#comment5dan menyegarkan halaman setelah melihat sekeliling, Anda tidak akan berada di jangkar dan halaman melompat-lompat. Apakah ada cara untuk mencegahnya dengan javascript? Sehingga tidak peduli apa pun Anda akan selalu menavigasi ke jangkar.

ThomasReggi
sumber
Apakah solusi jQuery oke atau Anda ingin js biasa?
mrtsherman

Jawaban:

16

Solusi ini tidak lagi disarankan karena perubahan perilaku browser. Lihat jawaban lainnya.

Pada dasarnya, jika jangkar digunakan, kami mengikat ke acara gulir jendela. Idenya adalah bahwa acara gulir pertama harus termasuk dalam pemosisian ulang otomatis yang dilakukan oleh browser. Ketika ini terjadi, kami melakukan reposisi kami sendiri dan kemudian menghapus acara terikat. Hal ini untuk mencegah gulungan halaman berikutnya mengganggu sistem.

$(document).ready(function() {
    if (window.location.hash) { 
        //bind to scroll function
        $(document).scroll( function() {
            var hash = window.location.hash
            var hashName = hash.substring(1, hash.length);
            var element;

            //if element has this id then scroll to it
            if ($(hash).length != 0) {
                element = $(hash);
            }
            //catch cases of links that use anchor name
            else if ($('a[name="' + hashName + '"]').length != 0)
            {
                //just use the first one in case there are multiples
                element = $('a[name="' + hashName + '"]:first');
            }

            //if we have a target then go to it
            if (element != undefined) {
                window.scrollTo(0, element.position().top);
            }
            //unbind the scroll event
            $(document).unbind("scroll");
        });
    }

});
mrtsherman
sumber
Satu kasus penggunaan yang saya pikirkan yang harus diperhitungkan adalah jika pengguna menggulir halaman sebelum pengguliran otomatis terjadi. Seingat saya, pengguliran otomatis hanya terjadi setelah halaman dimuat sepenuhnya. Jika pengguna menggulir sebelumnya maka autoscroll dibatalkan. Jadi, Anda memerlukan beberapa cara untuk membedakan antara scroll yang dimulai pengguna dan yang dimulai browser. Saya tidak tahu bagaimana melakukan ini, tetapi seingat saya itu mungkin.
mrtsherman
1
Booyah! Ini masalah larut malam yang menyenangkan. Saya memberi tahu bos saya bahwa itu salah Anda ketika saya tertidur di meja saya. Saya baru saja membuat perubahan cepat untuk menghapus pernyataan pengembalian. Ini mengganggu pelepasan yang saya tambahkan untuk acara gulir.
mrtsherman
Awalnya saya mendapatkan ini berfungsi dalam file contoh dasar kecil untuk memeriksanya. Setelah saya mengonfirmasi bahwa itu berhasil, saya bingung bagaimana itu tidak berfungsi dalam proyek saya. Melalui proses eliminasi saya berhasil menemukan deklarasi gaya tunggal di file css saya yang menyebabkan kesalahan. Itu adalah penerapan font eksternal. Saya membungkus kode Anda dalam sebuah fungsi dan sekarang meneruskannya ke handler $ (window) .load () di dalam handler doc.ready. Ini jahitan untuk bekerja sekarang (dengan sedikit flicker halaman awal). Terima kasih untuk kodenya! Beri tahu saya jika ini adalah perbaikan yang solid atau tidak.
ThomasReggi
1
Ini tidak akan berfungsi jika Anda memiliki konten yang dimuat setelah halaman dimuat; Contoh: memiliki 2 div yang akan diisi dari ajax dengan banner.
Desebal
@FlashThunder - dapatkah Anda mendefinisikan "tidak berfungsi"? Posting pesan konsol?
mrtsherman
152

Di Chrome, meskipun Anda memaksa scrollTop ke 0, ini akan melompat setelah acara scroll pertama.

Anda harus mengikat gulungan ke ini:

$(window).on('beforeunload', function() {
    $(window).scrollTop(0);
});

Jadi browser tertipu untuk percaya bahwa itu di awal sebelum refresh.

josetapadas
sumber
5
Jauh lebih berguna daripada jawaban yang diterima jika Anda tidak ingin dipusingkan dengan scrolling.
Dan Abramov
2
Ini tidak melakukan pekerjaan di Chrome 33. Maksud saya itu menggulir ke atas sebelum memuat halaman baru. Namun browser masih mengingat posisi gulir sebelumnya dan melakukan autoscroll yang sama ke posisi itu.
Haralan Dobrev
1
Diuji di Chrome 36, Firefox 30, dan IE 11. Bekerja dengan sangat baik!
Fizzix
24
Untuk implementasi non-jQuery: window.onbeforeunload = function(){ window.scrollTo(0,0); }
ProfNandaa
5
Mengapa Anda memilih acara 'beforeunload' daripada 'unload'. Pengujian saya menunjukkan bahwa yang terakhir memungkinkan untuk menghindari lompat ke atas sebelum halaman benar-benar dibongkar oleh browser.
Aleksandr Zonov
76

Untuk menonaktifkan pemulihan gulir otomatis cukup tambahkan tag ini ke bagian kepala.

<script>history.scrollRestoration = "manual"</script>

Itu tidak didukung oleh IE. Kompatibilitas browser.

imos
sumber
3
Ini akan menjadi jawaban terbaik jika tersedia di IE / Edge. Anda dapat memilihnya untuk diterapkan di sini: wpdev.uservoice.com/forums/257854-microsoft-edge-developer/…
The Chewy
4
Ini seharusnya menjadi jawaban yang benar di tahun 2019. Tidak ada metode lain yang 100% berhasil.
Limbo
2
Dapat mengonfirmasi bahwa ini adalah solusi terbaik. Solusi lain di sini tidak berfungsi di Safari Seluler dan bisa tersendat-sendat. Ini bekerja dengan sempurna.
pengguna3330820
20

Setelah beberapa kali gagal akhirnya saya berhasil melakukan trik tersebut. anzo benar di sini karena penggunaan beforeunloadakan membuat halaman melompat ke atas saat pengguna memuat ulang halaman atau mengklik link. Begitu unloadjuga cara yang jelas untuk melakukan ini.

$(window).on('unload', function() {
   $(window).scrollTop(0);
});

Cara Javascript (Terima kasih ProfNandaa ):

window.onunload = function(){ window.scrollTo(0,0); }

EDIT: 16/07/2015

Masalah lompatan masih ada dengan Firefox bahkan dengan unloadacara.

Janaka Dombawela
sumber
3
Solusi ini jauh lebih baik daripada beforeunloadsolusi karena mencegah melompat ke atas halaman saat memuat ulang dan mengklik tautan.
BradGreens
@BradGreens Dengan Chrome modern, peristiwa onunload juga dipicu saat pengguna beralih ke tab lain, yang tidak terduga. onbeforeunload masih merupakan solusi yang valid.
Telvin Nguyen
@TelvinNguyen Dapatkah Anda memberikan sumber daya apapun tentang ini? Saya menguji ini di google chrome 72 dan masih berfungsi dengan baik untuk saya.
Janaka Dombawela
@JanakaDombawela Apa yang saya nyatakan: Menggeser tab baru yang akan menyebabkan masalah tidak benar. Namun, Anda dapat melihat acara onunload dalam contoh ini tidak dipicu dengan benar, bahkan dengan jQuery 1.9.1 vs jQuery 1.8.3. onunload tidak dapat diandalkan. jsfiddle.net/6s4jhdug/3 (1.8.3) jsfiddle.net/frt45ue9 (1.9.1)
Telvin Nguyen
3

Berikut pendekatan yang lebih umum. Alih-alih mencoba mencegah browser menggulir (atau melompat ke atas sebagaimana tampilannya), saya hanya mengembalikan posisi sebelumnya pada halaman. Yaitu saya merekam y-offset halaman saat ini di localStorage dan menggulir ke posisi ini setelah halaman dimuat.

function storePagePosition() {
  var page_y = window.pageYOffset;
  localStorage.setItem("page_y", page_y);
}


window.addEventListener("scroll", storePagePosition);


var currentPageY;

try {
  currentPageY = localStorage.getItem("page_y");

  if (currentPageY === undefined) {
    localStorage.setItem("page_y") = 0;
  }

  window.scrollTo( 0, currentPageY );
} catch (e) {
    // no localStorage available
}
Oliver Schafeld
sumber
2

Anda bisa meletakkan # di akhir sehingga halaman akan dimuat di bagian atas.

Bekerja di semua browser, seluler dan desktop, karena sangat sederhana.

$(document).ready(function() {
var url = window.location.href;
console.log(url);
if( url.indexOf('#') < 0 ) {
    window.location.replace(url + "#");
} else {
    window.location.replace(url);
}

});

// Ini memuat halaman dengan # di akhir.

Daut
sumber
Jika saya mencoba ini di server saya secara langsung, ini berfungsi seperti ajaib. Tapi, cms saya memberi saya kesalahan mark-up. Saya tidak tahu apa itu.
alice
1
jika Anda menggunakan wordpress, ubah $ untuk jQuery
Herzling
1

Ini berhasil untuk saya.

    //Reset scroll top

    history.scrollRestoration = "manual"

    $(window).on('beforeunload', function(){
          $(window).scrollTop(0);
    });
Alex Bersenang-senang
sumber
-2

Kamu harus bisa.

Onload, periksa apakah window.location.hashmemiliki nilai. Jika ya, ambil elemen dengan id yang cocok dengan nilai hash. Temukan posisi elemen (panggilan rekursif ke offsetTop / offsetLeft) lalu teruskan nilai tersebut ke dalam window.scrollTo(x, y)metode.

Ini harus menggulir halaman ke elemen yang diinginkan.

nikmd23
sumber
3
Ini tidak mencegah browser melakukan gulir otomatis. Tentang itulah pertanyaan ini.
Haralan Dobrev