How to ignore popstate initial load, working with pjax
Asked Answered
D

5

12

I have been trying to get the forward an back browser buttons to work on a small site using pjax and have come up with the following code to handle class changes and fading in and out the various overlays.

However I have found that Chrome and Safari treats the initial page load as a popstate and so it is causing me grief. Is there anyway to stop this?

$(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);
  }
});
Durrell answered 25/5, 2012 at 15:8 Comment(0)
D
3

I actually found the solution within pjax itself.

Instead of doing:

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

which fired the popstate on the initial page load I did:

$(window).on('pjax:popstate', function() {...  
Durrell answered 26/5, 2012 at 20:26 Comment(0)
C
29

Tag the state when you call pushState(), then ignore all popstate events that don't have your tag. e.g.

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
}

Don't forget to call replaceState at page load so that you can handle the popstate when you get back to the initial page load.

$(function() { history.replaceState({ myTag: true }); });
Cataplasm answered 26/5, 2012 at 11:3 Comment(7)
I actually found that the solution is within pjax. So instead of doingDurrell
That's the only solution i found that works after the first call of a page, after a reload and in gecko/webkit/trident. Plus without changing the behavior browsers calling popstate! Great solution. Thanks!Tague
In my tests today, event.originalEvent doesn't exist in any current browsers. While a variation of this (using event.state) does seem to work in current versions of Chrome and Firefox, Safari (8.0.6) gets null back for event.state and I can't find any of the data pushed with pushState for later reference. Safari is the new IE6.Kleeman
@AdamTuttle .originalEvent is a field in jQuery's event object that references the original DOM event. See api.jquery.com/onCataplasm
Ah, fair enough, thanks! I was working in vanilla JS so didn't have that available.Kleeman
Wouldn't the call to replaceState ensure that myTag is true on every page? When would it evaluate to false?Leiva
@Leiva When a different script calls pushState without myTag.Cataplasm
D
3

I actually found the solution within pjax itself.

Instead of doing:

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

which fired the popstate on the initial page load I did:

$(window).on('pjax:popstate', function() {...  
Durrell answered 26/5, 2012 at 20:26 Comment(0)
S
2

The best long term fix is to up-vote https://code.google.com/p/chromium/issues/detail?id=63040 to get Google to fix this. They've known they're out of compliance with the HTML5 spec for about two years now.

Suspend answered 4/12, 2013 at 21:20 Comment(1)
It says Status: Fixed and a comment there: "Still not landed on Chrome 32 stable, fixed on Chrome Canary 34." - Feb 10, 2014.Achelous
A
1

In order to solve the initial page load as a popstate in safari and chrome browsers, we can use SetTimeOut function.

This simply works !!

  setTimeout( function() {
      window.addEventListener( 'popstate', myFunction, false );
    }, 500 );
Advent answered 8/3, 2016 at 11:19 Comment(0)
T
0
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);
    }
});

(A mootools solution)

Tain answered 15/7, 2015 at 10:19 Comment(1)
Welcome to Stack Overflow! Please explain what your code does and why it will solve the problem. An answer that just contains code (even if it's working) usually wont help the OP to understand their problem.Nianiabi

© 2022 - 2024 — McMap. All rights reserved.