Подтвердить что ты не робот

Window bind POPSTATE

Учитывая следующее:

$(window).bind("popstate", function() {
    alert('popstate');
});

При первой загрузке предупреждение срабатывает с FireFox и Chrome, но не с Safari. Почему это? Кто-нибудь еще видел это и знает, как лучше всего решить эту проблему?

Спасибо

4b9b3361

Ответ 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();

Отметьте здесь для получения дополнительной информации об этом решении