Skip to content
Permalink
Browse files

Fixed bubbling of live events (if an inner element handles an event f…

…irst - and stops progatation - then the parent event doesn't encounter the event). Thanks to Irae for the patch. Fixes bug #3980.
  • Loading branch information
jeresig committed Feb 9, 2009
1 parent 0ae7802 commit 9aa0c69c43bad9fce5ef7732692308afb2a38ec6
Showing with 43 additions and 7 deletions.
  1. +6 −2 src/core.js
  2. +5 −1 src/event.js
  3. +5 −0 test/index.html
  4. +24 −1 test/unit/event.js
  5. +3 −3 test/unit/selector.js
@@ -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++;
}
});
},
@@ -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;
@@ -213,6 +213,11 @@ <h2 id="userAgent"></h2>
<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>

@@ -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");
});

/*
@@ -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"] );

0 comments on commit 9aa0c69

Please sign in to comment.
You can’t perform that action at this time.