(Примечание: в соответствии с отзывами Шарки я включил код для обнаружения возврата)
Итак, я часто сталкивался с этими вопросами в SO, и недавно столкнулся с проблемой управления функциональностью кнопки возврата самостоятельно. После нескольких дней поиска лучшего решения для моего приложения (одностраничный с хэш-навигацией) я нашел простую, кросс-браузерную, безбиблиотечную систему для обнаружения кнопки «назад».
Большинство людей рекомендуют использовать:
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 для запуска события back, вы также можете добавить следующее (спасибо @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();
}
}
});
});