jQuery - evento hashchange

86

Estou usando:

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

para vincular uma função ao evento de mudança de hash. Isso parece funcionar no IE8, Firefox e Chrome, mas não no Safari e presumo que não na versão anterior do IE. Para esses navegadores, desejo desabilitar meu código JavaScript que usa o hash e o hashchangeevento.

Existe uma maneira com o jQuery que posso detectar se o navegador oferece suporte ao hashchangeevento? Talvez algo com jQuery.support...

Ian Herbert
fonte
4
jQuery hashchange event - o plugin jQuery funciona perfeitamente, mesmo no IE8. + é muito fácil de usar :)
enloz

Respostas:

36

Uma resposta atualizada aqui a partir de 2017, caso alguém precise, é que onhashchangeé bem suportado em todos os principais navegadores. Veja caniuse para detalhes. Para usá-lo com jQuery, nenhum plugin é necessário:

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

Ocasionalmente, encontro sistemas legados onde URLs hashbang ainda são usados ​​e isso é útil. Se você estiver construindo algo novo e usando links hash, eu sugiro que você considere usar a API pushState HTML5.

Kevin leary
fonte
2
Isso funciona bem, use window.location.hashpara acessar o hash atual.
Daniel Dewhurst
18

Há um plug-in hashchange que encerra a funcionalidade e os problemas entre navegadores disponíveis aqui .

James Westgate
fonte
Requerido apenas para <IE8
James Westgate
18

Uma abordagem diferente para o seu problema ...

Existem 3 maneiras de vincular o evento hashchange a um método:

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

Ou

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

Ou

<body onhashchange="doThisWhenTheHashChanges();">

Todos eles funcionam com IE 9, FF 5, Safari 5 e Chrome 12 no Win 7.

james.garriss
fonte
8

experimente o site oficial da Mozilla: https://developer.mozilla.org/en/DOM/window.onhashchange

cite o seguinte:

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

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

window.onhashchange = locationHashChanged;
Paul Lan
fonte
3

Acabei de ter o mesmo problema (falta de evento hashchange no IE7). Uma solução alternativa adequada aos meus objetivos era vincular o evento click dos links de alteração 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
fonte
1
você poderia usar $('a[href^="#"]')para obter links para hrefs começando com um hash, evitando a necessidade de um suplemento de classe
tobymackenzie
2

Observe que, no caso do IE 7 e do IE 9, se a instrução for verdadeira para ("onhashchange" no Windows), mas o window.onhashchange nunca será acionado, então é melhor armazenar o hash e verificar a cada 100 milissegundos se ele foi alterado ou não para todas as versões do 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
fonte
2
Não é demais para o navegador? pesquisar uma mudança de hash a cada 100 ms?
adardesign
5
seu código de amostra fez meu alerta do IE8 até eu abrir o gerenciador de tarefas e matar o processo :)
enloz
isso é porque há um erro de digitação, em vez de "storedHash" use "prevHash" e funcionará. Ele basicamente usou um nome de variável diferente daquele como foi declarado.
Nick
2

Que tal usar uma maneira diferente em vez do evento hash e ouvir popstate como.

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

Este método funciona bem na maioria dos navegadores que experimentei até agora.

Sven van den Boogaart
fonte
1
Popstate é ainda mais novo que o hashchange. Por exemplo, não é compatível com IE <10.
Arturo Torres Sánchez
0

Acho que Chris Coyier tem a solução para esse problema de hash, dê uma olhada em seu screencast:

Melhores práticas com conteúdo dinâmico

Sarfraz
fonte
Obrigado, vou dar uma olhada nisso.
Ian Herbert
0

Use Modernizr para detecção de recursos de recursos. Em geral, o jQuery oferece para detectar recursos do navegador: http://api.jquery.com/jQuery.support/ . No entanto, hashchange não está na lista.

O wiki da Modernizr oferece uma lista de bibliotecas para adicionar recursos HTML5 a navegadores antigos. A lista de hashchange inclui um ponteiro para a API HTML5 History do projeto , que parece oferecer a funcionalidade de que você precisa se quiser emular o comportamento em navegadores antigos.

koppor
fonte
0

Aqui está a versão atualizada de @ johnny.rodgers

A esperança ajuda alguém.

// 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
fonte