Window bind POPSTATE

Compte tenu de ce qui suit:

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

Lors de la première charge, les feux d'alerte avec FireFox et Chrome, mais pas Safari. Pourquoi donc? Quelqu'un d'autre a-t-il vu cela et sait comment résoudre le mieux?

Merci

La situation est maintenant inversée. Chrome a réparé le bug et déclenche maintenant le popstate sur le chargement de la page, mais Firefox 4 (depuis RC) est parti de la spécification et ne tire pas maintenant le popstate !

MISE À JOUR : La spécification HTML5 a été modifiée en 2011 pour indiquer que l'état de popstate ne doit pas être déclenché sur le chargement de la page. Firefox et Chrome font maintenant le bon choix depuis Firefox 4 et Chrome 34 .

Voir le code de pjax. Pjax est une bibliothèque open source assez populaire maintenant, donc la logique ci-dessous pourrait être la meilleure pour éviter ce problème.

 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

Dans le webkit, l'événement popstate est déclenché sur le chargement de la page. Pour éviter cela, ce travail facile fonctionne pour moi:

Chaque fois que je lance history.push history.push(...) j'ajoute l' historique de class versé au body -tag:

 history.push(...); $("body").addClass("historypushed"); 

Lorsque je lance l'événement popstate, je vérifie cette classe:

 $(window).bind('popstate', function(e) { if($("body").hasClass("historypushed")) { /* my code */ } }); 

Un moyen simple d'éviter ce problème est de définir le premier argument sur pushState sur true puis de vérifier contre onpsy. Semblable à l'exemple de pjax, mais un peu plus simple. L'exemple ci-dessous exécutera doSomething () pour chaque événement popstate, sauf pour la première charge de page.

 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(); } }); } } 

Il y a eu un bug dans Webkit qui a mal implémenté l'événement "popstate". Découvrez ce message simple expliquant le problème (petit spectacle cool et dis): http://www.bcherry.net/playground/pushstate

Ma suggestion serait de mettre en place votre propre tracker événement "popstate" pour Safari. Quelque chose comme ça:

 $(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 }); 

Vous pouvez envelopper cette déclaration dans un test de navigateur pour vérifier le safari. Encore mieux voir si "popstate" a été déclenché au moment où le DOM est prêt, puis appliquez la fonction interne pour remplacer l'implémentation. La seule chose que vous ne voulez pas arriver est de faire appel à deux événements popstate (duplication de la logique du gestionnaire d'événements, un excellent moyen de verrouiller l'interface utilisateur).

C'est ma solution de contournement.

 window.setTimeout(function() { window.addEventListener('popstate', function() { // ... }); }, 1000); 

Je convertisse @Nobu & @Tamlyn réponses dans un objet, j'ajoute aussi un petit correctif en ajoutant "window.history.state! == null". Dans certains navigateurs, l'historique existe, mais il est nul, de sorte qu'il ne fonctionnait pas.

 /** * 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 (eg 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; ... }); 

Cette réponse à une question similaire suggère de vérifier la vérité booléenne de l'événement. event.state dans le popstate événements popstate :

 window.addEventListener('popstate', function(event) { if (event.state) { alert('!'); } }, false); 

Vous pouvez également lier votre fonction de rappel à l'événement popstate comme ceci:

 window.onpopstate = callback(); 

Vérifiez ici pour plus d'informations sur cette solution