2011-01-03 6 views
6

ich dieses Problem habe (ich bin mit jQuery, aber ich bin es nicht darauf beschränkt):Onhashchange mit Browser-Buttons nur

Ich verwende eine Combo von Anchor Navigation (#id) und Anfragen Ajax . Um die Seiten zum Platzieren zu bringen (Anker-Navigation zu verwenden) oder Informationen (mit Ajax) abzurufen, verwende ich das Ereignis onhashchange.

EDIT: Ich hatte ein wenig Tippfehler. Ich habe vergessen zu prüfen, ob das mouseDown-Flag wahr ist und das hashchange-Ereignis ausgelöst wurde, also habe ich die if-Anweisung hinzugefügt.

mit jQuery sieht es wie folgt aus: (natürlich dieser Code in einer Funktion und initialisiert auf DOM Ladung gewickelt wird, aber es für die Frage, spielt keine Rolle)


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

nur Browser, um sicherzustellen, das onhashchange Unterstützung liest den Code ich es so verkapseln:


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

Meine Web-App in einer solchen Art und Weise hergestellt ist, dass ich nur die onhashchange Ereignis auslösen soll, wenn ich die Vor/zurück-Buttons im Browser getroffen. Zu tun, dass ich wie folgt tun:


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

Wenn ich nun im Ansichtsfenster klicken werde ich das Mousedown-Ereignis auslösen. Wenn das Mousedown-Ereignis ausgelöst wird, weiß ich, dass ich nicht den Browser klicken haben vor/zurück Tasten und ich kann das onhashchange Ereignis stoppen ein Flag wie folgt aus:


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 
    } 
    } 
} 

dies ein Problem für IE verursacht, da es Nähte können Sie Mausereignisse nicht an das Fensterobjekt (?) binden. IE wird das mousedown-Ereignis nie "sehen".

Um dieses IE Problem zu lösen, kann ich die Eigenschaft "clientY" nehmen. Diese Eigenschaft wird in allen Ereignisaufrufen in IE übergeben und teilt Ihnen die Koordinaten der Maus mit. Wenn e.clientY kleiner als 0 ist, befindet sich die Maus außerhalb des Ansichtsfensters und ich weiß, dass ich die Onhash-Änderung ausgelöst habe, indem ich auf die Zurück-/Vorwärts-Schaltflächen des Browsers geklickt habe. Es sieht nun wie folgt aus:


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 
    } 
    } 
} 

Diese Lösung wurde wie ein Zauber zu arbeiten, bis ich Unterstützung hinzufügen musste für auf der Tastatur mit den Pfeilen navigieren. Jetzt ist es egal, wo auf dem Bildschirm die Maus ist. Solange das IE-Fenster "aktiv" ist, wird das Keydown-Ereignis, das auf die Tastatureingabe wartet, beim Drücken der Tastatur ausgelöst. Dies bedeutet, dass die clientY-Prüfung nicht mehr wie vorgesehen funktioniert.

Das Problem:

Soweit ich weiß, muss die onhashchange an das Fenster-Objekt gebunden werden. Alle Ereignisse müssen innerhalb derselben Callback-Funktion verarbeitet werden, wenn ich ein Ereignis steuern möchte, indem ich auf ein anderes höre.

Wie kann ich das zum Funktionieren bringen?

+0

entdecken kann ("onhashchange" im Fenster) wird immer falsch zurückgeben, wenn es noch nicht definiert ist und es ist bereits definiert. Es bedeutet nicht, dass der Browser den Code auf einer Hash-Änderung tatsächlich ausführt. Dies ist ähnlich zu window.onload, das undefiniert ist, es sei denn, eine Funktion wurde tatsächlich zugewiesen, obwohl praktisch alle Browser es unterstützen. – qwertymk

+0

Ja, ich habe die Funktionserklärung absichtlich weggelassen, da ich sie für die Frage nicht relevant fand. Die Funktion, die das Ereignis hashchange bindet, wird aufgerufen, wenn das DOM geladen wird. – Patrik

Antwort

3

So einfach Put-

„Wie unterscheide ich zwischen einem Vor/Zurück-Taste drücken gegen die Navigation aus der Interaktion mit dem DOM kommen“.

Möglicherweise möchten Sie ein Flag haben, dass Sie, wenn Sie den Hash-Teil der URL aus Code ändern, dieses Flag setzen, das hashchange -Ereignis ignorieren und dann die Markierung aufheben. In diesem Fall wird das Ereignis ignoriert (eine Art umgekehrte Lösung, was Sie versuchen zu tun). Sie möchten das natürlich in eine Funktion einfügen.

Im Allgemeinen verwenden jedoch Anwendungen, die das Ereignis hashchange für die Navigation verwenden, häufig das Ereignis hashchange, um den Status der Anwendung zu ändern. Daher gibt es nur einen Einstiegspunkt und Sie müssen nicht unterscheiden, ob das Ereignis durch Browser-Navigation oder Dom-Interaktion generiert wird. Ich würde dir wahrscheinlich empfehlen, deinen Ansatz zu ändern.

Ich würde Sie auch darauf hinweisen, dass Geschichte über alle Browser unterstützt werden kann (sogar IE6 und IE7 mit einem iFrame-Hack). Werfen Sie einen Blick auf die jQuery history plugin

+0

Verdammt, ich wusste, dass es auf eine kürzere Art und Weise beschrieben werden könnte;) Das ist das Problem, der Hash-Teil wird nie aus dem Code gesetzt. Es wird vom Standard-Link-Verhalten eingestellt und verwendet den Browser-Verlauf, um mit den Browser-Schaltflächen vor und zurück zu navigieren. Das Ändern des Ansatzes ist keine Option. Meine Lösung funktionierte gut, bis ich die keyDown-Ereignisse implementieren musste. Auch habe ich nicht erwähnt, dass dies eine GT IE 7 gezielte Lösung ist, da wir diesen Teil mit den Benutzern steuern können. IE6 und 7 werden also kein Problem sein. – Patrik

+0

Über "Ändern des Status der Anwendung". Diese Lösung ist etwas anders, da sie eine Kombination aus animierter Anker-Navigation und Ajax-Aufrufen verwendet. Wenn es nur Ajax-Aufrufe wären, wäre das kein Problem. :) Wie auch immer, ich werde die Idee einer umgekehrten Lösung geben, um zu sehen, ob ich einen neuen Winkel finden kann, um das Problem anzugehen. Vielen Dank. – Patrik

+0

Ich musste etwas mit der Annäherung an andere Teile meines Codes ändern, was mich nur mit dem Hashchange-Ereignis für diese Funktion verließ. Es ist nicht sehr schön, aber es funktioniert für jetzt. – Patrik

1

Die Referenzbibliothek, dies zu erreichen: http://benalman.com/projects/jquery-bbq-plugin/

ich es benutzt und es funktioniert super

über das Setzen Denken „!“ nach "#" in der URL, so dass Google die Ajax-Seiten http://code.google.com/web/ajaxcrawling/docs/getting-started.html

+0

Ja, ich habe es angeschaut. Ich bin nicht besonders auf die Verwendung von Plugins (oder Code, den ich selbst nicht geschrieben habe). Vor allem Plugins, die viel mehr können, als ich brauche. In diesem Fall baue ich ein geschlossenes System, so dass Google die Seiten nie sehen wird. Aber trotzdem danke für den Link. Es ist eine großartige Referenz! – Patrik