Entonces, ahora que HTML5 se presenta history.pushState
para cambiar el historial de los navegadores, los sitios web comienzan a usar esto en combinación con Ajax en lugar de cambiar el identificador de fragmento de la URL.
Lamentablemente, eso significa que esas llamadas ya no se pueden detectar onhashchange
.
Mi pregunta es: ¿hay alguna forma confiable (piratear?) Para detectar cuándo se usa un sitio web history.pushState
? La especificación no establece nada sobre los eventos que se generan (al menos no pude encontrar nada).
Traté de crear una fachada y la reemplacé window.history
con mi propio objeto JavaScript, pero no tuvo ningún efecto.
Explicación adicional: estoy desarrollando un complemento de Firefox que necesita detectar estos cambios y actuar en consecuencia.
Sé que hubo una pregunta similar hace unos días que preguntaba si escuchar algunos eventos DOM sería eficiente, pero prefiero no confiar en eso porque estos eventos se pueden generar por muchas razones diferentes.
Actualizar:
Aquí hay un jsfiddle (use Firefox 4 o Chrome 8) que muestra que onpopstate
no se activa cuando pushState
se llama (¿o estoy haciendo algo mal? ¡Siéntase libre de mejorarlo!).
Actualización 2:
Otro problema (lateral) es que window.location
no se actualiza cuando se usa pushState
(pero ya leí sobre esto en SO, creo).
fuente
history
objeto. Eso puede ser innecesario en este caso.window.history
es de solo lectura, pero las propiedades del objeto de historial no lo son ... Muchas gracias por esta solución :)pushState
método nativo para su uso posterior. Entonces, en lugar de una variable global, elegí encapsular todo el código en un IIFE: en.wikipedia.org/wiki/Immediately-invoked_function_expressionSolía usar esto:
Es casi lo mismo que hizo galambalazs .
Sin embargo, generalmente es exagerado. Y podría no funcionar en todos los navegadores. (Solo me importa mi versión de mi navegador).
(Y deja una var
_wr
, por lo que es posible que desee envolverlo o algo. No me importó eso).fuente
Finalmente encontré la forma "correcta" de hacer esto. Requiere agregar un privilegio a su extensión y usar la página de fondo (no solo un script de contenido), pero funciona.
El evento que desea es
browser.webNavigation.onHistoryStateUpdated
, que se activa cuando una página usa lahistory
API para cambiar la URL. Solo se dispara para los sitios a los que tiene permiso de acceso, y también puede usar un filtro de URL para reducir aún más el correo no deseado si es necesario. Requiere elwebNavigation
permiso (y, por supuesto, el permiso del host para los dominios relevantes).La devolución de llamada del evento obtiene el ID de la pestaña, la URL a la que se está "navegando" y otros detalles similares. Si necesita realizar una acción en la secuencia de comandos de contenido en esa página cuando se dispara el evento, inyecte la secuencia de comandos relevante directamente desde la página de fondo o haga que la secuencia de comandos de contenido abra una
port
página de fondo cuando se cargue, guarde la página de fondo ese puerto en una colección indexada por ID de pestaña, y envía un mensaje a través del puerto relevante (desde la secuencia de comandos de fondo a la secuencia de comandos de contenido) cuando se desencadena el evento.fuente
¿Podrías unirte al
window.onpopstate
evento?https://developer.mozilla.org/en/DOM%3awindow.onpopstate
De los documentos:
fuente
history.go
,.back
) se llaman funciones. Pero no enpushState
. Aquí está mi intento de probarlo, tal vez hago algo mal: jsfiddle.net/fkling/vV9vd Parece solo relacionado de esa manera que si el historial fue cambiado porpushState
, el objeto de estado correspondiente se pasa al controlador de eventos cuando los otros métodos son llamados.Como estás preguntando acerca de un complemento de Firefox, aquí está el código que pude trabajar. Ya no se recomienda el uso y
unsafeWindow
se producen errores cuando se llama a pushState desde un script de cliente después de ser modificado:En cambio, hay una API llamada exportFunction que permite que la función se inyecte de
window.history
esta manera:fuente
unsafeWindow.history,
awindow.history
. No funcionaba para mí con unsafeWindow.La respuesta de galambalazs parches de mono
window.history.pushState
ywindow.history.replaceState
, pero por alguna razón dejó de funcionar para mí. Aquí hay una alternativa que no es tan buena porque usa encuestas:fuente
Creo que este tema necesita una solución más moderna.
Estoy seguro
nsIWebProgressListener
estaba por ahí, entonces me sorprende que nadie lo haya mencionado.De un framecript (para compatibilidad de e10s):
Luego escuchando en el
onLoacationChange
Aparentemente eso atrapará todos los pushState. Pero hay un comentario que advierte que "TAMBIÉN se dispara para pushState". Por lo tanto, necesitamos hacer un poco más de filtrado aquí para asegurarnos de que solo se trate de elementos de estado de inserción.
Basado en: https://github.com/jgraham/gecko/blob/55d8d9aa7311386ee2dabfccb481684c8920a527/toolkit/modules/addons/WebNavigation.jsm#L18
Y: recurso: //gre/modules/WebNavigationContent.js
fuente
Bueno, veo muchos ejemplos de reemplazo de la
pushState
propiedad de,history
pero no estoy seguro de que sea una buena idea, preferiría crear un evento de servicio basado en una API similar al historial para que pueda controlar no solo el estado de inserción sino también el estado de reemplazo también y abre puertas para muchas otras implementaciones que no dependen de la API de historial global. Por favor, consulte el siguiente ejemplo:Si necesitas el
EventEmitter
definición, el código anterior se basa en el emisor de eventos NodeJS: https://github.com/nodejs/node/blob/36732084db9d0ff59b6ce31e839450cd91a156be/lib/events.js .utils.inherits
La implementación se puede encontrar aquí: https://github.com/nodejs/node/blob/36732084db9d0ff59b6ce31e839450cd91a156be/lib/util.js#L970fuente
Prefiero no sobrescribir el método de historial nativo, por lo que esta implementación simple crea mi propia función llamada estado eventedPush que solo envía un evento y devuelve history.pushState (). De cualquier manera funciona bien, pero esta implementación me parece un poco más limpia, ya que los métodos nativos continuarán funcionando como esperan los futuros desarrolladores.
fuente
Basado en la solución dada por @gblazex , en caso de que desee seguir el mismo enfoque, pero utilizando las funciones de flecha, siga el ejemplo a continuación en su lógica de JavaScript:
Luego, implemente otra función
_notifyUrl(url)
que active cualquier acción requerida que pueda necesitar cuando se actualice la URL de la página actual (incluso si la página no se ha cargado)fuente
Como solo quería la nueva URL, he adaptado los códigos de @gblazex y @Alberto S. para obtener esto:
fuente
No creo que sea una buena idea modificar las funciones nativas, incluso si puede, y siempre debe mantener el alcance de su aplicación, por lo que un buen enfoque es no usar la función pushState global, en su lugar, use una propia:
Tenga en cuenta que si algún otro código usa la función pushState nativa, no obtendrá un desencadenador de evento (pero si esto sucede, debe verificar su código)
fuente
Como estados estándar:
necesitamos llamar a history.back () para activar WindowEventHandlers.onpopstate
Tan insted de:
hacer:
fuente