(Примітка. Відповідно до відгуків Шаркі, я включив код для виявлення зворотних просторів)
Таким чином, я часто бачив ці питання в програмі SO, і останнім часом я сам стикався з проблемою контролю функцій кнопки назад. Після кількох днів пошуку найкращого рішення для мого застосування (Single-Page with Hash Navigation), я створив просту, крос-браузерну, без бібліотеку систему виявлення кнопки "назад".
Більшість людей рекомендують використовувати:
window.onhashchange = function() {
//blah blah blah
}
Однак ця функція також буде викликана, коли користувач використовує вбудований елемент, який змінює хеш місцеположення. Не найкраща робота з користувачем, коли користувач клацає, а сторінка переходить назад або вперед.
Щоб дати вам загальний контур моєї системи, я заповнюю масив попередніми хешами, коли мій користувач рухається по інтерфейсу. Це виглядає приблизно так:
function updateHistory(curr) {
window.location.lasthash.push(window.location.hash);
window.location.hash = curr;
}
Досить прямо вперед. Я роблю це для забезпечення крос-браузерної підтримки, а також підтримки для старих браузерів. Просто перенесіть новий хеш у функцію, і він збереже його для вас, а потім змінить хеш (який потім буде введено в історію браузера).
Я також використовую кнопку повернення на сторінці, яка переміщує користувача між сторінками за допомогою lasthash
масиву. Це виглядає приблизно так:
function goBack() {
window.location.hash = window.location.lasthash[window.location.lasthash.length-1];
//blah blah blah
window.location.lasthash.pop();
}
Таким чином, це перемістить користувача назад до останнього хешу та видалить останній хеш із масиву (у мене зараз немає кнопки переадресації).
Так. Як визначити, користувався чи не користувач моєю кнопкою повернення на сторінці чи кнопкою браузера?
Спочатку я подивився window.onbeforeunload
, але безрезультатно - це викликається лише у випадку, якщо користувач збирається змінювати сторінки. Це не відбувається в односторінковому додатку, що використовує хеш-навігацію.
Отже, після ще одного копання я побачив рекомендації щодо спроби встановити змінну прапора. Проблема з цим у моєму випадку полягає в тому, що я б спробував встановити це, але оскільки все асинхронно, воно не завжди буде встановлено вчасно для заяви if у хеші. .onMouseDown
не завжди викликали натискання, і додавання його до onclick ніколи не призведе до цього досить швидко.
Це коли я почав роздивлятися різницю між document
і window
. Моє остаточне рішення - встановити прапор за допомогою document.onmouseover
та відключити його з використанням document.onmouseleave
.
Що трапляється, це те, що, якщо миша користувача знаходиться в області документа (читайте: візуалізована сторінка, але виключаючи рамку браузера), мій булевий параметр встановлений на true
. Як тільки миша покидає область документа, булева повертається до false
.
Таким чином я можу змінити своє window.onhashchange
на:
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();
}
}
}
Ви помітите чек на #undefined
. Це тому, що якщо в моєму масиві немає історії, вона повертається undefined
. Я використовую це, щоб запитати користувача, чи хочуть вони вийти, використовуючи window.onbeforeunload
подію.
Отже, коротше, і для людей, які не обов’язково використовують кнопку повернення на сторінці або масив для зберігання історії:
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
}
}
І ось у вас це є. простий, з трьох частин спосіб виявити використання кнопок "назад" та елементів на сторінці, що стосується навігації по хешу.
Редагувати:
Щоб користувач не використовував backspace для запуску події назад, ви також можете включити наступне (Спасибі @thetoolman у цьому запитанні ):
$(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();
}
}
});
});