Fixed bubbling of live events (if an inner element handles an event first - and stops progatation - then the parent event doesn't encounter the event). Thanks to Irae for the patch. Fixes bug #3980.

This commit is contained in:
John Resig 2009-02-09 23:29:57 +00:00
parent 0ae78024c2
commit 9aa0c69c43
5 changed files with 43 additions and 7 deletions

View file

@ -346,14 +346,18 @@ jQuery.fn = jQuery.prototype = {
},
closest: function( selector ) {
var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null;
var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null,
closer = 0;
return this.map(function(){
var cur = this;
while ( cur && cur.ownerDocument ) {
if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) )
if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
jQuery.data(cur, "closest", closer);
return cur;
}
cur = cur.parentNode;
closer++;
}
});
},

View file

@ -571,9 +571,13 @@ function liveHandler( event ){
}
});
elems.sort(function(a,b) {
return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest");
});
jQuery.each(elems, function(){
if ( this.fn.call(this.elem, event, this.fn.data) === false )
stop = false;
return (stop = false);
});
return stop;

View file

@ -213,6 +213,11 @@ Z</textarea>
<span>...</span><a id="linkWithNoHrefWithTabIndex" tabindex="1">Eat some funyuns</a><span>...</span>
<span>...</span><a id="linkWithNoHrefWithNegativeTabIndex" tabindex="-1">Eat some funyuns</a><span>...</span>
</div>
<div id="liveHandlerOrder">
<span id="liveSpan1"><a href="#" id="liveLink1"></a></span>
<span id="liveSpan2"><a href="#" id="liveLink2"></a></span>
</div>
</div>
</dl>

View file

@ -474,7 +474,7 @@ test("toggle(Function, Function, ...)", function() {
});
test(".live()/.die()", function() {
expect(42);
expect(46);
var submit = 0, div = 0, livea = 0, liveb = 0;
@ -611,6 +611,29 @@ test(".live()/.die()", function() {
// Cleanup
jQuery("#nothiddendivchild").die("click");
// Verify that .live() ocurs and cancel buble in the same order as
// we would expect .bind() and .click() without delegation
var lived = 0, livee = 0;
// bind one pair in one order
jQuery('span#liveSpan1 a').live('click', function(){ lived++; return false; });
jQuery('span#liveSpan1').live('click', function(){ livee++; });
jQuery('span#liveSpan1 a').click();
equals( lived, 1, "Verify that only one first handler occurred." );
equals( livee, 0, "Verify that second handler don't." );
// and one pair in inverse
jQuery('#liveHandlerOrder span#liveSpan2').live('click', function(){ livee++; });
jQuery('#liveHandlerOrder span#liveSpan2 a').live('click', function(){ lived++; return false; });
jQuery('span#liveSpan2 a').click();
equals( lived, 2, "Verify that only one first handler occurred." );
equals( livee, 0, "Verify that second handler don't." );
// Cleanup
jQuery("span#liveSpan1 a, span#liveSpan1, span#liveSpan2 a, span#liveSpan2").die("click");
});
/*

View file

@ -189,7 +189,7 @@ test("child and adjacent", function() {
reset();
t( "Last Child", "p:last-child", ["sap"] );
t( "Last Child", "a:last-child", ["simon1","anchor1","mark","yahoo","anchor2","simon"] );
t( "Last Child", "a:last-child", ["simon1","anchor1","mark","yahoo","anchor2","simon","liveLink1","liveLink2"] );
t( "Nth-child", "#main form#form > *:nth-child(2)", ["text1"] );
t( "Nth-child", "#main form#form > :nth-child(2)", ["text1"] );
@ -278,7 +278,7 @@ test("pseudo (:) selectors", function() {
expect(53);
t( "First Child", "p:first-child", ["firstp","sndp"] );
t( "Last Child", "p:last-child", ["sap"] );
t( "Only Child", "a:only-child", ["simon1","anchor1","yahoo","anchor2"] );
t( "Only Child", "a:only-child", ["simon1","anchor1","yahoo","anchor2","liveLink1","liveLink2"] );
t( "Empty", "ul:empty", ["firstUL"] );
t( "Enabled UI Element", "#form input:not([type=hidden]):enabled", ["text1","radio1","radio2","check1","check2","hidden2","name"] );
t( "Disabled UI Element", "#form input:disabled", ["text2"] );
@ -290,7 +290,7 @@ test("pseudo (:) selectors", function() {
t( "Text Contains", "a:contains('Google Groups (Link)')", ["groups"] );
t( "Text Contains", "a:contains('(Link)')", ["groups"] );
t( "Element Preceded By", "p ~ div", ["foo","fx-queue","fx-tests", "moretests","tabindex-tests"] );
t( "Element Preceded By", "p ~ div", ["foo","fx-queue","fx-tests", "moretests","tabindex-tests", "liveHandlerOrder"] );
t( "Not", "a.blog:not(.link)", ["mark"] );
t( "Not - multiple", "#form option:not(:contains('Nothing'),#option1b,:selected)", ["option1c", "option1d", "option2b", "option2c", "option3d", "option3e"] );
//t( "Not - complex", "#form option:not([id^='opt']:nth-child(-n+3))", [ "option1a", "option1d", "option2d", "option3d", "option3e"] );