onpopstate change javascript jquery html5 history

javascript - change - pushstate



ventana de enlace POPSTATE (8)

Dado lo siguiente:

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

En la primera carga, la alerta se activa con Firefox y Chrome, pero no con Safari. ¿Porqué es eso? ¿Alguien más ha visto esto y sabe cómo resolverlo mejor?

Gracias


Convierto las respuestas de @Nobu y @Tamlyn en un objeto, también agrego una pequeña corrección al agregar "window.history.state! == null". En algunos navegadores existe history.state, pero es nulo, por lo que no funcionó.

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

Gracias @Nobu! Gracias @Tamlyn!


En webkit, el evento popstate se activa en la carga de la página. Para evitar esto, este trabajo fácil alrededor de mí funciona:

Cada vez que dispare history.push(...) agrego la class historypqueez al body -tag:

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

Cuando desencadeno el evento popstate, verifico esta clase:

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


Esta es mi solución.

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


Hubo un error en Webkit que implementó incorrectamente el evento "popstate". Echa un vistazo a esta sencilla publicación que explica el problema (pequeño show y comenta): http://www.bcherry.net/playground/pushstate

Mi sugerencia sería implementar su propio rastreador de eventos "popstate" para Safari. Algo como esto:

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

Podrías envolver esa declaración en una prueba del navegador para verificar si hay un safari. Aún mejor si se ha activado "popstate" para cuando el DOM esté listo y luego aplique la función interna para reemplazar la implementación. Lo único que no quiere que suceda es que se activen dos eventos popstate (duplicando la lógica del controlador de eventos, una excelente manera de bloquear la interfaz de usuario).


La situación ahora se invierte. Chrome corrigió el error y ahora dispara popstate en la carga de la página, ¡pero Firefox 4 (desde RC) se ha apartado de la especificación y ahora no dispara popstate !

ACTUALIZACIÓN : la especificación de HTML5 se modificó en 2011 para indicar que popstate no debe activarse al cargar la página. Tanto Firefox como Chrome ahora hacen lo correcto a partir de Firefox 4 y Chrome 34 .


Una forma fácil de evitar este problema es establecer el primer argumento en pushState en verdadero y luego comparar con onpopstate. Similar al ejemplo pjax pero un poco más directo. El siguiente ejemplo ejecutará doSomething () para cada evento de popstate excepto para la primera carga de la página.

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


Ver el código de pjax. pjax es una biblioteca de código abierto bastante popular ahora, por lo que la siguiente lógica podría ser la mejor para evitar este problema.

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


Esta respuesta a una pregunta similar sugiere verificar la verdad booleana de event.state en el controlador de eventos popstate :

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

También puede vincular su función de devolución de llamada al evento popstate como este:

window.onpopstate = callback();

Consulte here para obtener más información sobre esa solución