2012-03-27 12 views
0

Ich habe eine Klasse von div MyClass Ich möchte zwei Handler anschließen. Diese Klasse wird dynamisch generiert und das ist, was ich tue:jquery Einstellung der Reihenfolge der Handler

$('#MainDiv').on({ 
click: function() { Handler1($(this)); } 
}, '.MyClass'); 

$('#SpecialChildDiv').on({ 
click: function() { Handler2($(this)); } 
}, '.MyClass'); 

Wie steuere ich die Handler zuerst genannt wird? Handler2 führt einige zusätzliche Arbeiten aus, aber es wird nicht bei jeder MyClass aufgerufen, da es nicht im SpecialChildDiv enthalten ist. Ich möchte, dass Handler 2 nach Handler1 aufgerufen wird.

Danke.

+0

Das sind ZWEI verschiedene Handler ... Ich bin mir nicht sicher, was Sie fragen ... – Neal

+0

Es tut mir leid, aber was soll ''myClass'' dort am Ende tun? http://api.jquery.com/on/ – Blazemonger

+0

Ich vermute, es funktioniert von innen nach außen. –

Antwort

1

Da die SpecialChildDiv vermutlich ein Nachkomme von MainDiv ist, wird es zuerst genannt werden. Dies liegt daran, dass das Ereignis vom Ziel aufblubbert und die Handler aufruft, die auf dem Weg nach oben in dieser Reihenfolge gefunden wurden.

Eine Möglichkeit wäre, den Anruf zu Handler2 im SpecialChildDiv Handler zu machen asynchrone durch ein setTimeout verwenden.

$('#MainDiv').on({ 
    click: function() { 
     Handler1($(this)); 
    } 
}, '.MyClass'); 

$('#SpecialChildDiv').on({ 
    click: function() { 
     setTimeout($.proxy(function() { 
      Handler2($(this)); 
     }, this), 0); 
    } 
}, '.MyClass'); 

So der Handler selbst wird sofort aufgerufen werden, aber Ihre Handler2 Funktion, bis die nicht ausgeführt werden, nachdem die Handler1 genannt wurde.

Ich habe auch $.proxy verwendet, um den korrekten this Wert in der Funktion beizubehalten, die Sie an setTimeout übergeben.


Ein wenig off topic, aber Sie können Ihren Code sauberer machen, wenn Sie so Handler1 und Handler2 ändern, dass this ein Verweis auf das Element ist, sondern es als Argument vorbei ...

$('#MainDiv').on({ 
    click: Handler1 
}, '.MyClass'); 

$('#SpecialChildDiv').on({ 
    click: function() { 
     setTimeout($.proxy(Handler2, this), 0); 
    } 
}, '.MyClass'); 

Sie müssen nur innerhalb Ihrer Funktionen $(this) tun, um das Element in ein jQuery-Objekt zu wickeln. Dies kann jedoch nicht nützlich sein, wenn andere Argumente übergeben werden müssen.

Basierend auf Ihrem Kommentar unten scheint es, dass diese Technik auf verschiedene untergeordnete Elemente angewendet werden muss.

Um den Code vertrocknen Sie eine Fabrik für die Klick-Handler erstellen ...

function async_handler_factory(the_handler) { 
    return function() { 
     setTimeout($.proxy(function() { 
      the_handler($(this)); 
     }, this), 0); 
    }; 
} 

... es dann wie folgt verwenden ...

$('#MainDiv').on({ 
    click: Handler1 
}, '.MyClass'); 

$('#SpecialChildDiv').on({ 
    click: async_handler_factory(Handler2) 
}, '.MyClass'); 

$('#AnotherChildDiv').on({ 
    click: async_handler_factory(Handler3) 
}, '.MyClass'); 

So ist es die Gleiches Prinzip. Nur dass Sie Ihre HandlerN Funktion an async_handler_factory übergeben, und es wird die Handler-Funktion click erstellen und zurückgeben, die das gleiche wie meinen ursprünglichen Code durch Aufruf der HandlerN in einer setTimeout.


nur Verwirrung über $.proxy zu vermeiden, ist hier eine aktualisierte Version, die es überflüssig macht.

function async_handler_factory(the_handler) { 
    return function() { 
     var self = this; 
     setTimeout(function() { 
      the_handler($(self)); 
     }, 0); 
    }; 
} 

Dies zeigt, dass es tatsächlich die setTimeout ist, die Ihre Arbeit Lösung machen wird.


EDIT: Hat einen anderen Namen für async_handler_factory an verschiedenen Orten. Fest.

+1

Die Jungs, die JQuery gebaut haben, haben wirklich an alles gedacht !! Danke, dass Sie mich mit dieser Proxy-Funktion vertraut gemacht haben! – frenchie

+0

@Frenchie: Gern geschehen. Ja, das '$ .proxy' ist praktisch, und ich denke, es ist ein bisschen netter als' var self = this; 'dann' Handler2 ($ (self)); ' –

+0

Ich habe gerade an etwas gedacht: Gibt es einen Weg dazu mach es anders herum? Mit anderen Worten, funktioniert die Proxy-Funktion nicht in SpecialChildDiv, funktioniert es mit MainDiv? Es gibt tatsächlich mehrere verschiedene SpecialChildDiv und ich möchte das Proxy-Problem für jeden Fall vermeiden. – frenchie

0

Also die zweite auf Klick nicht nennen - es nennen, nachdem der erste Handler getan wird:

$('#MainDiv').on({ 
    click: function (e) { 
     Handler1($(this)); 
     if ($(e.target).attr('id')==="SpecialChildDiv") { 
      specialChildClick(); 
     } 
    } 
}, '.MyClass'); 

specialChildClick = function() { 
    Handler2($('#SpecialChildDiv')); 
} 
+0

Ja, ich dachte daran, das zu tun, aber es ist unordentlich in meinem Fall. Die MyClass ist eigentlich ein Datum in einem benutzerdefinierten Kalender und ich möchte die Logik des Kalenders von der Logik des anderen Steuerelements, das den Kalender verwendet, trennen. – frenchie

Verwandte Themen