2011-01-03 8 views
6

ho questo problema (sto usando jQuery ma non sono limitati ad esso):Onhashchange con i tasti del browser solo

sto usando una combinazione di Anchor navigazione (#id) e richieste Ajax . Per far sì che le pagine si spostino (usando la navigazione di ancoraggio) o per recuperare informazioni (usando Ajax), io uso l'evento onhashchange.

MODIFICA: Ho avuto un piccolo errore di battitura. Ho dimenticato di controllare se il flag mouseDown fosse vero e l'evento hashchange è stato attivato, quindi ho aggiunto quella if statement.

con jQuery che appare così: (ovviamente questo codice è avvolto in una funzione e inizializzata sul carico DOM ma non importa per la domanda)


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

per assicurare che solo browsers sostenere l'onhashchange legge il codice che ho incapsulare in questo modo:


if ('onhashchange' in window) { 
    $(window).bind('hashchange', function(e) { } 
} 

mio web app è fatta in modo tale che io voglio solo l'evento onhashchange per attivare quando ho colpito le/pulsanti avanti e indietro nel browser. Per farlo mi piace:


if ('onhashchange' in window) { 
    $(window).bind('mousedown hashchange', function(e) { } 
} 

Ora, se clicco sul viewport, attiverò l'evento mouse. Se l'evento MouseDown viene attivato lo so che non ho scegliere il browser avanti/indietro e posso fermare l'evento onhashchange utilizzando una bandiera come questo:


var mouseDown = false; 

if ('onhashchange' in window) { 
    $(window).bind('mousedown hashchange', function(e) { 
    if (e.type === 'mousedown') { 
     mouseDown = true; 
    } 

    if (mouseDown && e.type === 'hashchange') { 
     // if the mousedown event was triggered and when the haschange event triggers, 
     // we need to stop the hashchange event and restore the mouseDown flag 
     mouseDown = false; 
     e.stopPropagation();   
    } 

    if (!mouseDown && e.type === 'hashchange') { 
     // Do the onhashchange stuff here 
    } 
    } 
} 

Ciò causa un problema per IE dal momento che non è possibile associare gli eventi del mouse all'oggetto della finestra (?). IE non vedrà mai "l'evento falso".

Per risolvere questo problema IE Posso prendere la proprietà "clientY". Questa proprietà è passata in tutte le chiamate di eventi in IE e ti dice le coordinate del mouse. Se e.clientY è inferiore a 0, il mouse si trova al di fuori del viewport e saprò che ho attivato lo scambio di onhashc facendo clic sui pulsanti Indietro/Avanti del browser. E ora si presenta così:


var mouseDown = false; 

if ('onhashchange' in window) { 
    $(window).bind('mousedown hashchange', function(e) { 
    // IE: Use e.clientY to check if the mouse position was within the viewport (i.e. not a nagative value for Y) 
    // !IE: Use e.type 
    if (e.type === 'mousedown' || e.clientY > 0) { 
     mouseDown = true; 
    } 

    if (mouseDown && e.type === 'hashchange') { 
     // if the mousedown event was triggered and when the haschange event triggers, 
     // we need to stop the hashchange event and restore the mouseDown flag 
     mouseDown = false; 
     e.stopPropagation();   
    } 
    if (!mouseDown && e.type === 'hashchange') { 
     // Do the onhashchange stuff here 
    } 
    } 
} 

Questa soluzione stava lavorando come un fascino fino ho dovuto aggiungere il supporto per la navigazione con le frecce della tastiera. Ora non importa dove si trova il mouse sullo schermo. Finché la finestra di IE è "attiva", l'evento di keydown che ascolta i trigger di input della tastiera quando si colpisce la tastiera. Ciò significa che il controllo clientY non funziona più come previsto.

Il problema:

Per quanto ne so, l'onhashchange deve essere associato all'oggetto finestra. Tutti gli eventi devono essere elaborati con la stessa funzione di callback se voglio essere in grado di controllare un evento ascoltando un altro.

Come posso farlo funzionare?

+0

('onhashchange' nella finestra) restituirà sempre false se non è stato ancora definito e true è già definito. Ciò non significa che il browser eseguirà effettivamente il codice su un hashchange Questo è simile a window.onload che non è definito a meno che una funzione non sia stata effettivamente assegnata ad esso, anche se praticamente tutti i browser lo supportano. – qwertymk

+0

Sì, ho intenzionalmente omesso la dichiarazione della funzione poiché non la vedevo come rilevante per la domanda. La funzione che associa l'evento hashchange viene chiamata quando viene caricato il DOM. – Patrik

risposta

3

Così, semplicemente PUT

"come faccio a distinguere tra un avanti/indietro premere il pulsante di navigazione vs provenienti da interagire con il DOM".

Si consiglia di disporre di un flag tale che quando si modifica la parte hash dell'URL dal codice, si imposta questo flag, si ignora l'evento hashchange, quindi si disattiva il flag. Nel qual caso l'evento verrà ignorato (una sorta di soluzione inversa rispetto a ciò che stai cercando di fare). Ovviamente vorrai avvolgerlo in una funzione.

In generale, tuttavia, le applicazioni che utilizzano l'evento hashchange per la navigazione spesso utilizzano l'evento hashchange come mezzo per modificare lo stato dell'applicazione. Pertanto, esiste un solo punto di accesso e non è necessario distinguere tra se l'evento è generato dall'interazione tra navigazione del browser e dom. Probabilmente ti consiglierei di cambiare approccio.

Vorrei anche indicarvi il fatto che la cronologia può essere supportata su tutti i browser (anche IE6 e IE7 utilizzando un hack iFrame). Date un'occhiata al jQuery history plugin

+0

Accidenti, sapevo che poteva essere descritto in un modo più breve;) Questo è il problema, la parte hash non viene mai impostata dal codice. Viene impostato dal comportamento di collegamento predefinito e utilizza la cronologia del browser per spostarsi avanti e indietro con i pulsanti del browser. Cambiare l'approccio non è un'opzione. La mia soluzione ha funzionato bene fino a quando non ho dovuto implementare gli eventi keyDown. Inoltre non ho menzionato che questa è una soluzione mirata a GT IE 7 poiché possiamo controllare quella parte con gli utenti. Quindi IE6 e 7 non costituiranno alcun problema. – Patrik

+0

Informazioni su "Modifica dello stato dell'applicazione". Questa soluzione è leggermente diversa poiché utilizza una combinazione di navigazione animata di ancoraggio e chiamate ajax. Se fossero solo chiamate ajax, questo non sarebbe un problema. :) In ogni caso, darò l'idea di una soluzione inversa per vedere se riesco a trovare una nuova angolazione per affrontare il problema. Grazie. – Patrik

+0

Ho dovuto fare alcune modifiche con l'approccio ad altre parti del mio codice lasciandomi solo l'evento hashchange per questa funzione. Non è molto bello ma funziona per ora. – Patrik

1

La biblioteca di riferimento per raggiungere questo obiettivo: http://benalman.com/projects/jquery-bbq-plugin/

ho usato e funziona benissimo

pensare a mettere "!" dopo "#" nell'URL, in modo che google possa scoprire le pagine Ajax http://code.google.com/web/ajaxcrawling/docs/getting-started.html

+0

Sì, l'ho guardato. Non sono particolarmente interessato all'utilizzo di plug-in (o codice che non ho scritto io stesso per quella questione). Soprattutto i plugin che fanno molto di più di quello di cui ho bisogno. In questo caso sto costruendo un sistema chiuso, quindi Google non vedrà mai le pagine. Ma grazie comunque per il link. È un ottimo riferimento! – Patrik

Problemi correlati