Estoy usando History API para mi aplicación web y tengo un problema. Hago llamadas Ajax para actualizar algunos resultados en la página y uso history.pushState () para actualizar la barra de ubicación del navegador sin recargar la página. Luego, por supuesto, uso window.popstate para restaurar el estado anterior cuando se hace clic en el botón Atrás.
El problema es bien conocido: Chrome y Firefox tratan ese evento popstate de manera diferente. Si bien Firefox no lo enciende en la primera carga, Chrome lo hace. Me gustaría tener el estilo de Firefox y no activar el evento en la carga, ya que solo actualiza los resultados con exactamente los mismos en la carga. ¿Existe una solución alternativa excepto usar History.js ? La razón por la que no tengo ganas de usarlo es: necesita demasiadas bibliotecas JS por sí mismo y, dado que necesito que se implemente en un CMS con demasiado JS, me gustaría minimizar el JS que estoy poniendo en él. .
Entonces, me gustaría saber si hay una manera de hacer que Chrome no inicie 'popstate' al cargar o, tal vez, alguien intentó usar History.js ya que todas las bibliotecas se combinaron en un solo archivo.
Respuestas:
En Google Chrome en la versión 19, la solución de @spliter dejó de funcionar. Como señaló @johnnymire, history.state en Chrome 19 existe, pero es nulo.
Mi solución es agregar window.history.state! == null para verificar si el estado existe en window.history:
Lo probé en todos los navegadores principales y en las versiones 19 y 18 de Chrome. Parece que funciona.
fuente
in
ynull
verificar con solo!= null
ya que eso también se solucionaráundefined
.null
en sushistory.pushState()
métodos comohistory.pushState(null,null,'http//example.com/)
. Por supuesto, eso probablemente sería la mayoría de los usos (así es como está configurado en jquery.pjax.js y la mayoría de las otras demostraciones). Pero si los navegadores se implementanwindow.history.state
(como FF y Chrome 19+), window.history.state podría no ser nulo en una actualización o después de reiniciar el navegadorEn caso de que no desee tomar medidas especiales para cada controlador que agregue a onpopstate, mi solución puede ser interesante para usted. Una gran ventaja de esta solución es también que los eventos onpopstate se pueden manejar antes de que finalice la carga de la página.
Simplemente ejecute este código una vez antes de agregar cualquier controlador onpopstate y todo debería funcionar como se esperaba (también conocido como en Mozilla ^^) .
Cómo funciona:
Chrome, Safari y probablemente otros navegadores webkit activan el evento onpopstate cuando se carga el documento. Esto no está previsto, por lo que bloqueamos los eventos popstate hasta el primer ciclo de bucle de eventos después de que se haya cargado el documento. Esto se realiza mediante las llamadas preventDefault y stopImmediatePropagation (a diferencia de stopPropagation, stopImmediatePropagation detiene instantáneamente todas las llamadas al controlador de eventos).Sin embargo, dado que el readyState del documento ya está en "completo" cuando Chrome activa onpopstate por error, permitimos los eventos opopstate, que se activaron antes de que finalice la carga del documento, para permitir llamadas a onpopstate antes de que se cargue el documento.
Actualización 23-04-2014: se corrigió un error por el cual los eventos popstate se bloqueaban si el script se ejecutaba después de cargar la página.
fuente
window.history.state
falla en la recarga si se estableció un estado. Configuración de la variable antes del código desordenado de pushState. Su solución es elegante y puede colocarse encima de otros scripts, sin afectar al resto del código base. Gracias.Usar solo setTimeout no es una solución correcta porque no tiene idea de cuánto tiempo llevará cargar el contenido, por lo que es posible que el evento popstate se emita después del tiempo de espera.
Aquí está mi solución: https://gist.github.com/3551566
fuente
La solución se ha encontrado en jquery.pjax.js líneas 195-225 :
fuente
Una solución más directa que reimplementar pjax es establecer una variable en pushState y verificar la variable en popState, por lo que el popState inicial no se dispara de manera inconsistente en la carga (no es una solución específica de jquery, solo se usa para eventos):
fuente
window.history.ready
siempre es cierto.!window.history.ready && !ev.originalEvent.state
- esas dos cosas nunca se definen cuando actualizo la página. por lo tanto, no se ejecuta ningún código.El evento onpopstate inicial de Webkit no tiene un estado asignado, por lo que puede usar esto para verificar el comportamiento no deseado:
Una solución integral, que permita la navegación de regreso a la página original, se basaría en esta idea:
Si bien esto aún podría dispararse dos veces (con una navegación ingeniosa), se puede manejar simplemente con una verificación contra el href anterior.
fuente
window.history.state
también es nula en iOS. Solo comprobar si la propiedad e.state es nula es suficiente.Esta es mi solución.
fuente
Esta es mi solución:
fuente
La mejor manera de hacer que Chrome no active popstate en la carga de una página es votando a favor https://code.google.com/p/chromium/issues/detail?id=63040 . ¡Saben que Chrome no cumple con la especificación HTML5 durante dos años completos y aún no lo han solucionado!
fuente
En caso de uso,
event.state !== null
regresar en el historial a la primera página cargada no funcionará en navegadores que no sean móviles. Utilizo sessionStorage para marcar cuándo comienza realmente la navegación ajax.fuente
Las soluciones presentadas tienen un problema en la recarga de la página. Lo siguiente parece funcionar mejor, pero solo he probado Firefox y Chrome. Utiliza la actualidad, que parece haber una diferencia entre
e.event.state
ywindow.history.state
.fuente
e.event
no está definidoSé que preguntaste en contra, pero realmente deberías usar History.js, ya que elimina un millón de incompatibilidades de navegadores. Seguí la ruta de reparación manual solo para descubrir más tarde que había más y más problemas que solo descubrirás más adelante. Realmente no es tan difícil hoy en día:
Y lea la api en https://github.com/browserstate/history.js
fuente
Esto resolvió mi problema. Todo lo que hice fue establecer una función de tiempo de espera que retrasa la ejecución de la función el tiempo suficiente para perder el evento popstate que se activa al cargar la página
fuente
Puede crear un evento y dispararlo después de su controlador de carga.
Tenga en cuenta que esto está un poco roto en Chrome / Safari, pero envié el parche a WebKit y debería estar disponible pronto, pero es la forma "más correcta".
fuente
Esto funcionó para mí en Firefox y Chrome
fuente