jQuery - evento hashchange

86

Estoy usando:

$(window).bind( 'hashchange', function(e) { });

para vincular una función al evento de cambio de hash. Esto parece funcionar en IE8, Firefox y Chrome, pero no en Safari y supongo que no en la versión anterior de IE. Para estos navegadores, quiero deshabilitar mi código JavaScript que usa el hash y el hashchangeevento.

¿Hay alguna forma con jQuery que pueda detectar si el navegador es compatible con el hashchangeevento? Quizás algo con jQuery.support...

Ian Herbert
fuente
4
Evento jQuery hashchange : el complemento jQuery funciona perfectamente, incluso en IE8. + es muy fácil de usar :)
enloz

Respuestas:

69

Puede detectar si el navegador admite el evento mediante:

if ("onhashchange" in window) {
  //...
}

Ver también:

Christian C. Salvadó
fuente
Gracias por eso y por la rápida respuesta.
Ian Herbert
19
Tenga en cuenta que IE8 que se ejecuta en el modo de compatibilidad de IE7 informa verdadero para 'onhashchange' en la ventana, aunque el evento no es compatible -de jQuery Mobile
Vikas
36

Una respuesta actualizada aquí a partir de 2017, si alguien la necesita, es que onhashchange es compatible con todos los navegadores principales. Consulte caniuse para obtener más detalles. Para usarlo con jQuery no se necesita ningún complemento:

$( window ).on( 'hashchange', function( e ) {
    console.log( 'hash changed' );
} );

De vez en cuando me encuentro con sistemas heredados en los que todavía se usan las URL de hashbang y esto es útil. Si está creando algo nuevo y usando enlaces hash, le sugiero que considere usar la API pushState de HTML5 en su lugar.

Kevin Leary
fuente
2
Esto funciona bien, utilícelo window.location.hashpara acceder al hash actual.
Daniel Dewhurst
18

Hay un complemento hashchange que resume la funcionalidad y los problemas entre navegadores disponibles aquí .

James Westgate
fuente
Solo requerido para <IE8
James Westgate
18

Un enfoque diferente a su problema ...

Hay 3 formas de vincular el evento hashchange a un método:

<script>
    window.onhashchange = doThisWhenTheHashChanges;
</script>

O

<script>
    window.addEventListener("hashchange", doThisWhenTheHashChanges, false);
</script>

O

<body onhashchange="doThisWhenTheHashChanges();">

Todos estos funcionan con IE 9, FF 5, Safari 5 y Chrome 12 en Win 7.

james.garriss
fuente
8

pruebe el sitio oficial de Mozilla: https://developer.mozilla.org/en/DOM/window.onhashchange

cite lo siguiente:

if ("onhashchange" in window) {
    alert("The browser supports the hashchange event!");
}

function locationHashChanged() {
    if (location.hash === "#somecoolfeature") {
        somecoolfeature();
    }
}

window.onhashchange = locationHashChanged;
Paul Lan
fuente
3

Me encontré con el mismo problema (falta de evento hashchange en IE7). Una solución alternativa que se adaptaba a mis propósitos era vincular el evento de clic de los enlaces de cambio de hash.

<a class='hash-changer' href='#foo'>Foo</a>

<script type='text/javascript'>

if (("onhashchange" in window) && !($.browser.msie)) { 

    //modern browsers 
    $(window).bind('hashchange', function() {
        var hash = window.location.hash.replace(/^#/,'');
        //do whatever you need with the hash
    });

} else {

    //IE and browsers that don't support hashchange
    $('a.hash-changer').bind('click', function() {
        var hash = $(this).attr('href').replace(/^#/,'');
        //do whatever you need with the hash
    });

}

</script>
johnny.rodgers
fuente
1
que podría usar $('a[href^="#"]')para obtener enlaces a hrefs que comiencen con un hash, evitando la necesidad de agregar una clase
tobymackenzie
2

Tenga en cuenta que en el caso de IE 7 e IE 9, si la declaración dará verdadero para ("onhashchange" en Windows) pero el window.onhashchange nunca se activará, por lo que es mejor almacenar el hash y verificarlo después de cada 100 milisegundos si ha cambiado o no para todas las versiones de IE.

    if (("onhashchange" in window) && !($.browser.msie)) { 
         window.onhashchange = function () { 
              alert(window.location.hash);             
         }            
         // Or $(window).bind( 'hashchange',function(e) {  
         //       alert(window.location.hash); 
         //   });              
    }
    else { 
        var prevHash = window.location.hash;
        window.setInterval(function () {
           if (window.location.hash != prevHash) {
              prevHash = window.location.hash;
              alert(window.location.hash);
           }
        }, 100);
    }
Khan Salahuddin
fuente
2
¿No es esto demasiado para que lo maneje el navegador? para sondear un cambio de hash cada 100 ms?
adardesign
5
su código de muestra hizo que mi IE8 alertara hasta que abrí el administrador de tareas y maté el proceso :)
enloz
eso es porque hay un error tipográfico, en lugar de "storedHash" use "prevHash" y funcionará. Básicamente usó un nombre de variable diferente de cómo se declaró.
Nick
2

¿Qué hay de usar una forma diferente en lugar del evento hash y escuchar popstate like?

window.addEventListener('popstate', function(event)
{
    if(window.location.hash) {
            var hash = window.location.hash;
            console.log(hash);
    }
});

Este método funciona bien en la mayoría de los navegadores que he probado hasta ahora.

Sven van den Boogaart
fuente
1
Popstate es incluso más nuevo que hashchange. Por ejemplo, no es compatible con IE <10.
Arturo Torres Sánchez
0

Utilice Modernizr para la detección de funciones. En general, jQuery ofrece detectar funciones del navegador: http://api.jquery.com/jQuery.support/ . Sin embargo, hashchange no está en la lista.

La wiki de Modernizr ofrece una lista de bibliotecas para agregar capacidades HTML5 a navegadores antiguos. La lista de hashchange incluye un puntero a la API de historial HTML5 del proyecto , que parece ofrecer la funcionalidad que necesitaría si quisiera emular el comportamiento en navegadores antiguos.

koppor
fuente
0

Aquí está la versión actualizada de @ johnny.rodgers

La esperanza ayuda a alguien.

// ie9 ve ie7 return true but never fire, lets remove ie less then 10
if(("onhashchange" in window) && navigator.userAgent.toLowerCase().indexOf('msie') == -1){ // event supported?
    window.onhashchange = function(){
        var url = window.location.hash.substring(1);
        alert(url);
    }
}
else{ // event not supported:
    var storedhash = window.location.hash;
    window.setInterval(function(){
        if(window.location.hash != storedhash){
            storedhash = window.location.hash;
            alert(url);
        }
    }, 100);
}
Deniz Porsuk
fuente