Как игнорировать начальную загрузку popstate, работая с pjax

Я пытался заставить кнопки браузера вперед и назад работать на небольшом сайте с использованием pjax и придумал следующий код для обработки изменений класса и появления и исчезновения различных наложений.

Однако я обнаружил, что Chrome и Safari рассматривают первоначальную загрузку страницы как всплывающее состояние, и поэтому это вызывает у меня горе. Есть ли способ остановить это?

$(window).on("popstate", function() {
  if ($('body').hasClass('info')) {
    $('body').removeClass("info").addClass("work");
    $('.info_overlay').fadeOut(duration);
    alert('popstate');

  } else if ($('body').hasClass('work')) {
    $('body').removeClass("work").addClass("info");
    $('.info_overlay').fadeIn(duration);    

  } else {
    $('body').removeClass("project").addClass("work");
    $('.project_overlay').fadeOut(duration);
  }
});

person Sam Quayle    schedule 25.05.2012    source источник


Ответы (5)


Пометьте состояние, когда вы вызываете pushState(), затем игнорируйте все события popstate, которые не имеют вашего тега. например

history.pushState({ myTag: true }, ...)

$(window).on("popstate", function(e) {
  if (!e.originalEvent.state.myTag) return; // not my problem
  // rest of your popstate handler goes here
}

Не забудьте вызвать replaceState при загрузке страницы, чтобы вы могли обрабатывать всплывающее состояние, когда вернетесь к начальной загрузке страницы.

$(function() { history.replaceState({ myTag: true }); });
person Sean Hogan    schedule 26.05.2012
comment
Я действительно обнаружил, что решение находится в pjax. Поэтому вместо того, чтобы делать - person Sam Quayle; 27.05.2012
comment
Это единственное решение, которое я нашел, которое работает после первого вызова страницы, после перезагрузки и в gecko/webkit/trident. Плюс без изменения поведения браузеров, вызывающих popstate! Отличное решение. Спасибо! - person griffla; 16.05.2013
comment
В моих сегодняшних тестах event.originalEvent не существует ни в одном из текущих браузеров. Хотя вариант этого (с использованием event.state), похоже, работает в текущих версиях Chrome и Firefox, Safari (8.0.6) возвращает null вместо event.state, и я не могу найти никаких отправленных данных. с pushState для дальнейшего использования. Safari — это новый IE6. - person Adam Tuttle; 01.07.2015
comment
@AdamTuttle .originalEvent — это поле в объекте события jQuery, которое ссылается на исходное событие DOM. См. api.jquery.com/on. - person Sean Hogan; 02.07.2015
comment
Ах, справедливо, спасибо! Я работал в vanilla JS, поэтому у меня его не было. - person Adam Tuttle; 02.07.2015
comment
Разве вызов replaceState не гарантирует, что myTag будет true на каждой странице? Когда он будет оцениваться как false? - person Shreyas; 20.11.2015
comment
@Shreyas Когда другой скрипт вызывает pushState без myTag. - person Sean Hogan; 21.11.2015

На самом деле я нашел решение в самом pjax.

Вместо того, чтобы делать:

$(window).on('popstate', function() { ... 

который запустил popstate при начальной загрузке страницы, которую я сделал:

$(window).on('pjax:popstate', function() {...  
person Sam Quayle    schedule 26.05.2012

Лучшее долгосрочное решение проблемы — проголосовать за https://code.google.com/p/chromium/issues/detail?id=63040, чтобы Google исправил это. Они знали, что не соответствуют спецификации HTML5, уже около двух лет.

person Dave    schedule 04.12.2013
comment
Там написано Status: Fixed и комментарий: Все еще не добавлено в стабильную версию Chrome 32, исправлено в Chrome Canary 34. — 10 февраля 2014 г. - person MMachinegun; 28.04.2014

Чтобы разрешить начальную загрузку страницы как всплывающее состояние в браузерах Safari и Chrome, мы можем использовать функцию SetTimeOut.

Это просто работает!!

  setTimeout( function() {
      window.addEventListener( 'popstate', myFunction, false );
    }, 500 );
person Thiru    schedule 08.03.2016

var StateHelper = {

    pushState: function(url) {
        if(window.history.pushState) {
            window.history.pushState({"popstate": true}, '', url);
        }
    },

    updateStateData: function(stateData) {
        if(window.history.replaceState) {
            window.history.replaceState(stateData, '', window.location.href);
        }
    }
};

/**
 * NOTE: Webkit fires popstate event initial. So we modify the current state, but in the
 * event we still get null. So we can differentiate.
 */
StateHelper.updateStateData({"popstate": true});
window.addEvent('popstate', function(e) {
    if(e.event.state && e.event.state.popstate) {
        window.fireEvent('pophistory', e);
    }
});

(Решение mootools)

person guest    schedule 15.07.2015
comment
Добро пожаловать в Stack Overflow! Пожалуйста, объясните, что делает ваш код и почему он решит проблему. Ответ, который просто содержит код (даже если он работает), обычно не поможет ОП понять их проблему. - person SuperBiasedMan; 15.07.2015