it-swarm.asia

Cara Mendeteksi peristiwa Tombol Kembali Peramban - Lintas Peramban

Bagaimana Anda secara definitif mendeteksi apakah pengguna telah menekan tombol kembali di browser atau tidak? 

Bagaimana Anda menerapkan penggunaan tombol kembali di dalam halaman di dalam aplikasi web satu halaman menggunakan sistem #URL

Kenapa tidak tombol kembali browser menyalakan acara mereka sendiri !?

147
Xarus

(Catatan: Sesuai umpan balik Sharky, saya telah memasukkan kode untuk mendeteksi backspaces)

Jadi, saya sering melihat pertanyaan-pertanyaan ini di SO, dan baru-baru ini mengalami masalah dalam mengontrol fungsi tombol kembali sendiri. Setelah beberapa hari mencari solusi terbaik untuk aplikasi saya (Satu Halaman dengan Navigasi Hash), saya telah membuat sistem perpustakaan sederhana, lintas-browser, dan kurang untuk mendeteksi tombol kembali.

Kebanyakan orang merekomendasikan menggunakan:

window.onhashchange = function() {
 //blah blah blah
}

Namun, fungsi ini juga akan dipanggil ketika pengguna menggunakan elemen dalam halaman yang mengubah hash lokasi. Bukan pengalaman pengguna terbaik ketika pengguna Anda mengklik dan halaman berjalan mundur atau maju.

Untuk memberi Anda garis besar umum sistem saya, saya mengisi array dengan hash sebelumnya saat pengguna saya bergerak melalui antarmuka. Itu terlihat seperti ini:

function updateHistory(curr) {
    window.location.lasthash.Push(window.location.hash);
    window.location.hash = curr;
}

Cukup lurus ke depan. Saya melakukan ini untuk memastikan dukungan lintas browser, serta dukungan untuk browser lama. Cukup sampaikan hash baru ke fungsi, dan itu akan menyimpannya untuk Anda dan kemudian mengubah hash (yang kemudian dimasukkan ke dalam sejarah browser).

Saya juga menggunakan tombol kembali di dalam halaman yang menggerakkan pengguna di antara halaman menggunakan array lasthash. Ini terlihat seperti ini:

function goBack() {
    window.location.hash = window.location.lasthash[window.location.lasthash.length-1];
    //blah blah blah
    window.location.lasthash.pop();
}

Jadi ini akan memindahkan pengguna kembali ke hash terakhir, dan menghapus hash terakhir dari array (saya tidak punya tombol maju sekarang).

Begitu. Bagaimana cara mendeteksi apakah pengguna telah menggunakan tombol kembali di-halaman saya, atau tombol browser?

Pada awalnya saya melihat window.onbeforeunload, tetapi tidak berhasil - itu hanya disebut jika pengguna akan mengubah halaman. Ini tidak terjadi dalam aplikasi satu halaman menggunakan navigasi hash.

Jadi, setelah menggali lagi, saya melihat rekomendasi untuk mencoba mengatur variabel flag. Masalah dengan ini dalam kasus saya, adalah bahwa saya akan mencoba untuk mengaturnya, tetapi karena semuanya asinkron, itu tidak akan selalu diatur dalam waktu untuk pernyataan if dalam perubahan hash. .onMouseDown tidak selalu dipanggil dengan klik, dan menambahkannya ke onclick tidak akan pernah memicunya cukup cepat.

Ini adalah ketika saya mulai melihat perbedaan antara document, dan window. Solusi terakhir saya adalah mengatur flag menggunakan document.onmouseover, dan menonaktifkannya menggunakan document.onmouseleave.

Yang terjadi adalah ketika mouse pengguna berada di dalam area dokumen (baca: halaman yang diberikan, tetapi tidak termasuk bingkai browser), boolean saya disetel ke true. Segera setelah mouse meninggalkan area dokumen, boolean beralih ke false.

Dengan cara ini, saya dapat mengubah window.onhashchange saya menjadi:

window.onhashchange = function() {
    if (window.innerDocClick) {
        window.innerDocClick = false;
    } else {
        if (window.location.hash != '#undefined') {
            goBack();
        } else {
            history.pushState("", document.title, window.location.pathname);
            location.reload();
        }
    }
}

Anda akan mencatat cek untuk #undefined. Ini karena jika tidak ada riwayat yang tersedia di array saya, ia mengembalikan undefined. Saya menggunakan ini untuk bertanya kepada pengguna apakah mereka ingin pergi menggunakan acara window.onbeforeunload.

Jadi, singkatnya, dan untuk orang-orang yang tidak perlu menggunakan tombol kembali di-halaman atau array untuk menyimpan sejarah:

document.onmouseover = function() {
    //User's mouse is inside the page.
    window.innerDocClick = true;
}

document.onmouseleave = function() {
    //User's mouse has left the page.
    window.innerDocClick = false;
}

window.onhashchange = function() {
    if (window.innerDocClick) {
        //Your own in-page mechanism triggered the hash change
    } else {
        //Browser back button was clicked
    }
}

Dan begitulah. sederhana, tiga bagian cara untuk mendeteksi penggunaan tombol kembali vs elemen-elemen dalam halaman sehubungan dengan navigasi hash.

EDIT:

Untuk memastikan bahwa pengguna tidak menggunakan backspace untuk memicu acara kembali, Anda juga dapat memasukkan yang berikut (Terima kasih kepada @thetoolman di Pertanyaan ini ):

$(function(){
    /*
     * this swallows backspace keys on any non-input element.
     * stops backspace -> back
     */
    var rx = /INPUT|SELECT|TEXTAREA/i;

    $(document).bind("keydown keypress", function(e){
        if( e.which == 8 ){ // 8 == backspace
            if(!rx.test(e.target.tagName) || e.target.disabled || e.target.readOnly ){
                e.preventDefault();
            }
        }
    });
});
134
Xarus

Anda dapat mencoba popstate event handler, mis:

window.addEventListener('popstate', function(event) {
    // The popstate event is fired each time when the current history entry changes.

    var r = confirm("You pressed a Back button! Are you sure?!");

    if (r == true) {
        // Call Back button programmatically as per user confirmation.
        history.back();
        // Uncomment below line to redirect to the previous page instead.
        // window.location = document.referrer // Note: IE11 is not supporting this.
    } else {
        // Stay on the current page.
        history.pushState(null, null, window.location.pathname);
    }

    history.pushState(null, null, window.location.pathname);

}, false);

Catatan: Untuk hasil terbaik, Anda harus memuat kode ini hanya pada halaman tertentu di mana Anda ingin menerapkan logika untuk menghindari masalah yang tidak terduga lainnya.

Acara popstate dipecat setiap kali ketika entri riwayat saat ini berubah (pengguna menavigasi ke negara baru). Itu terjadi ketika pengguna mengklik pada tombol Kembali/Maju browser atau ketika history.back(), history.forward(), history.go() metode dipanggil secara terprogram.

Properti event.state adalah acara sama dengan objek status sejarah.

Untuk sintaks jQuery, lilitkan (untuk menambahkan pendengar genap setelah dokumen siap):

(function($) {
  // Above code here.
})(jQuery);

Lihat juga: window.onpopstate saat memuat halaman


Lihat juga contoh di Aplikasi Halaman Tunggal dan pushState HTML5 halaman:

<script>
// jQuery
$(window).on('popstate', function (e) {
    var state = e.originalEvent.state;
    if (state !== null) {
        //load content with ajax
    }
});

// Vanilla javascript
window.addEventListener('popstate', function (e) {
    var state = e.state;
    if (state !== null) {
        //load content with ajax
    }
});
</script>

Ini harus kompatibel dengan Chrome 5+, Firefox 4+, IE 10+, Safari 6+, Opera 11.5+ dan sejenisnya.

53
kenorb

Saya telah berjuang dengan persyaratan ini selama beberapa waktu dan mengambil beberapa solusi di atas untuk mengimplementasikannya. Namun, saya menemukan sebuah pengamatan dan tampaknya bekerja di browser Chrome, Firefox dan Safari + Android dan iPhone 

Pemuatan halaman:

window.history.pushState({page: 1}, "", "");

window.onpopstate = function(event) {

  // "event" object seems to contain value only when the back button is clicked
  // and if the pop state event fires due to clicks on a button
  // or a link it comes up as "undefined" 

  if(event){
    // Code to handle back button or prevent from navigation
  }
  else{
    // Continue user action through link or button
  }
}

Beri tahu saya jika ini membantu. Jika saya melewatkan sesuatu, saya akan dengan senang hati mengerti.

11
Itzmeygu

Dalam javascript, tipe navigasi 2 berarti tombol kembali atau maju browser diklik dan browser sebenarnya mengambil konten dari cache.

if(performance.navigation.type == 2)
{
    //Do your code here
}
7
Hasan Badshah

Browser: https://jsfiddle.net/Limitlessisa/axt1Lqoz/

Untuk kontrol seluler: https://jsfiddle.net/Limitlessisa/axt1Lqoz/show/

$(document).ready(function() {
  $('body').on('click touch', '#share', function(e) {
    $('.share').fadeIn();
  });
});

// geri butonunu yakalama
window.onhashchange = function(e) {
  var oldURL = e.oldURL.split('#')[1];
  var newURL = e.newURL.split('#')[1];

  if (oldURL == 'share') {
    $('.share').fadeOut();
    e.preventDefault();
    return false;
  }
  //console.log('old:'+oldURL+' new:'+newURL);
}
.share{position:fixed; display:none; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,.8); color:white; padding:20px;
<!DOCTYPE html>
<html>

<head>
    <title>Back Button Example</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

</head>

<body style="text-align:center; padding:0;">
    <a href="#share" id="share">Share</a>
    <div class="share" style="">
        <h1>Test Page</h1>
        <p> Back button press please for control.</p>
    </div>
</body>

</html>

3
Limitless isa

Inilah pendapat saya. Asumsinya adalah, ketika URL berubah tetapi tidak ada klik dalam document terdeteksi, itu adalah browser kembali (ya, atau meneruskan) Klik pengguna direset setelah 2 detik untuk membuatnya berfungsi pada halaman yang memuat konten melalui Ajax:

(function(window, $) {
  var anyClick, consoleLog, debug, delay;
  delay = function(sec, func) {
    return setTimeout(func, sec * 1000);
  };
  debug = true;
  anyClick = false;
  consoleLog = function(type, message) {
    if (debug) {
      return console[type](message);
    }
  };
  $(window.document).click(function() {
    anyClick = true;
    consoleLog("info", "clicked");
    return delay(2, function() {
      consoleLog("info", "reset click state");
      return anyClick = false;
    });
  });
  return window.addEventListener("popstate", function(e) {
    if (anyClick !== true) {
      consoleLog("info", "Back clicked");
      return window.dataLayer.Push({
        event: 'analyticsEvent',
        eventCategory: 'test',
        eventAction: 'test'
      });
    }
  });
})(window, jQuery);
2
TomTom101

Saya dapat menggunakan beberapa jawaban di utas ini dan yang lainnya untuk membuatnya berfungsi di IE dan Chrome/Edge. history.pushState untuk saya tidak didukung di IE11.

if (history.pushState) {
    //Chrome and modern browsers
    history.pushState(null, document.title, location.href);
    window.addEventListener('popstate', function (event) {
        history.pushState(null, document.title, location.href);
    });
}
else {
    //IE
    history.forward();
}
1
Arsalan Siddiqui

Document.mouseover tidak berfungsi untuk IE dan FireFox . Namun saya telah mencoba ini:

$(document).ready(function () {
  setInterval(function () {
    var $sample = $("body");
    if ($sample.is(":hover")) {
      window.innerDocClick = true;
    } else {
      window.innerDocClick = false;
    }
  });

});

window.onhashchange = function () {
  if (window.innerDocClick) {
    //Your own in-page mechanism triggered the hash change
  } else {
    //Browser back or forward button was pressed
  }
};

Ini berfungsi untuk Chrome dan IE dan bukan FireFox. Masih bekerja untuk memperbaiki FireFox. Cara mudah untuk mendeteksi klik tombol Kembali/Maju dari browser dipersilahkan, tidak terutama di JQuery tetapi juga AngularJS atau Javascript biasa. 

1
Dhruv Gupta
if (window.performance && window.performance.navigation.type == window.performance.navigation.TYPE_BACK_FORWARD) {
  alert('hello world');
}

Ini adalah satu-satunya solusi yang berfungsi untuk saya (ini bukan situs web onsite). Ini bekerja dengan Chrome, Firefox, dan Safari.

0
escanxr

Saya menyelesaikannya dengan melacak acara asli yang memicu hashchange (baik itu gesekan, klik atau roda), sehingga acara tersebut tidak akan keliru dengan pendaratan sederhana di halaman, dan menggunakan bendera tambahan di setiap binding acara saya. Browser tidak akan mengatur bendera lagi ke false ketika menekan tombol kembali:

var evt = null,
canGoBackToThePast = true;

$('#next-slide').on('click touch', function(e) {
    evt = e;
    canGobackToThePast = false;
    // your logic (remember to set the 'canGoBackToThePast' flag back to 'true' at the end of it)
}
0
user1025495
 <input style="display:none" id="__pageLoaded" value=""/>


 $(document).ready(function () {
        if ($("#__pageLoaded").val() != 1) {

            $("#__pageLoaded").val(1);


        } else {
            shared.isBackLoad = true;
            $("#__pageLoaded").val(1);  

            // Call any function that handles your back event

        }
    });

Kode di atas bekerja untuk saya. Pada browser seluler, ketika pengguna mengklik tombol kembali, kami ingin mengembalikan status halaman sesuai kunjungan sebelumnya.

0
Ashwin

Ini pasti akan berfungsi (Untuk mendeteksi klik tombol kembali)

$(window).on('popstate', function(event) {
 alert("pop");
});
0
rohan parab

Lihat ini:

history.pushState(null, null, location.href);
    window.onpopstate = function () {
        history.go(1);
    };

itu bekerja dengan baik ...

0
Jorge Rocha