Window bind POPSTATE
Учитывая следующее:
$(window).bind("popstate", function() {
alert('popstate');
});
При первой загрузке предупреждение срабатывает с FireFox и Chrome, но не с Safari. Почему это? Кто-нибудь еще видел это и знает, как лучше всего решить эту проблему?
Спасибо
Ответы
Ответ 1
Теперь ситуация изменилась. Chrome исправил ошибку и теперь запускает popstate при загрузке страницы, но Firefox 4 (начиная с RC) отошел от спецификации, а теперь не запускает popstate!
UPDATE. Спецификация HTML5 была изменена в 2011 году, когда state popstate не должен запускаться при загрузке страницы. И Firefox, и Chrome теперь делают правильные действия с Firefox 4 и Chrome 34.
Ответ 2
См. код из pjax. pjax - довольно популярная библиотека с открытым исходным кодом, поэтому логика ниже может быть лучшей, чтобы избежать этой проблемы.
var popped = ('state' in window.history), initialURL = location.href
$(window).bind('popstate', function(event) {
// Ignore inital popstate that some browsers fire on page load
var initialPop = !popped && location.href == initialURL
popped = true
if ( initialPop ) return
...
https://github.com/defunkt/jquery-pjax/blob/master/jquery.pjax.js
Ответ 3
В webkit событие popstate запускается при загрузке страницы. Чтобы этого избежать, эта легкая работа работает для меня:
Каждый раз, когда я запускаю history.push(...)
, я добавляю class
historypushed в body
-tag:
history.push(...);
$("body").addClass("historypushed");
Когда я запускаю событие popstate, я проверяю этот класс:
$(window).bind('popstate', function(e) {
if($("body").hasClass("historypushed")) {
/* my code */
}
});
Ответ 4
Легкий способ избежать этой проблемы - установить первый аргумент pushState на true, а затем проверить на onpopstate. Подобно примеру pjax, но немного более прямолинейному. В приведенном ниже примере будет выполняться doSomething() для каждого всплывающего события, за исключением загрузки первой страницы.
function setupPopState() {
if (history.popState) {
# immediately replace state to ensure popstate works for inital page
history.replaceState(true, null, window.location.pathname);
$(window).bind('popstate', function(event) {
if (event.originalEvent.state) {
doSomething();
}
});
}
}
Ответ 5
В Webkit произошла ошибка, которая неправильно реализовала событие "popstate" . Посмотрите этот простой пост, объяснив проблему (круто покажите и скажите): http://www.bcherry.net/playground/pushstate
Мое предложение состояло в том, чтобы реализовать собственный трекер событий "popstate" для Safari. Что-то вроде этого:
$(window).load(function(){
function fire_popstate(){
$(this).trigger("popstate"); // fire it when the page first loads
}
var lasthash = window.location.hash;
setInterval(function(){
var currenthash = window.location.hash;
if(lasthash != currenthash){
fire_popstate();
}
}, 500);//check every half second if the url has changed
});
Вы можете обернуть этот оператор в тесте браузера, чтобы проверить сафари. Еще лучше посмотреть, был ли "popstate" запущен к моменту готовности DOM, а затем применить внутреннюю функцию для замены реализации. Единственное, чего вы не хотите, - это запустить два всплывающих события (дублирование логики обработчика событий, отличный способ заблокировать пользовательский интерфейс).
Ответ 6
Это мое обходное решение.
window.setTimeout(function() {
window.addEventListener('popstate', function() {
// ...
});
}, 1000);
Ответ 7
Я конвертирую @Nobu и @Tamlyn ответы в объект, я также добавляю немного
исправить, добавив "window.history.state! == null". В некоторых браузерах
history.state существует, но он null, поэтому он не работал.
/**
* The HTML5 spec was changed in 2011 to state popstate should not
* fired on page load. Chrome(34) & Firefox(4) has fixed the bug but
* some browsers (e.g. Safari 5.1.7) are still fire the popstate on
* the page load. This object created from the Pjax Library to handle
* this issue.
*/
var popstatePageloadFix = {
popped : ('state' in window.history && window.history.state !== null),
initialUrl : location.href,
initialPop : false,
init : function() {
this.initialPop = !this.popped && location.href == this.initialUrl;
this.popped = true;
return this.initialPop;
}
};
$(window).on("popstate", function (event) {
// Ignore initial popstate that some browsers fire on page load
if ( popstatePageloadFix.init() ) return;
...
});
Ответ 8
Этот ответ на аналогичный вопрос предлагает проверить логическую истину event.state
в обработчике событий popstate
:
window.addEventListener('popstate', function(event) {
if (event.state) {
alert('!');
}
}, false);
Вы также можете связать свою функцию обратного вызова с событием popstate
следующим образом:
window.onpopstate = callback();
Отметьте здесь для получения дополнительной информации об этом решении