refactor specialAll into add and remove hooks for existing special events, live now accepts optional data param like bind, fixes #4612 and #4613, thanks to Mike Helgeson
This commit is contained in:
parent
287ecdbf67
commit
71efbdd3b2
61
src/event.js
61
src/event.js
|
@ -60,10 +60,15 @@ jQuery.event = {
|
||||||
handler.type = namespaces.slice().sort().join(".");
|
handler.type = namespaces.slice().sort().join(".");
|
||||||
|
|
||||||
// Get the current list of functions bound to this event
|
// Get the current list of functions bound to this event
|
||||||
var handlers = events[ type ];
|
var handlers = events[ type ],
|
||||||
|
special = this.special[ type ] || {};
|
||||||
|
|
||||||
if ( this.specialAll[ type ] ) {
|
if ( special.add ) {
|
||||||
this.specialAll[ type ].setup.call( elem, data, namespaces );
|
var modifiedHandler = special.add.call( elem, handler, data, namespaces );
|
||||||
|
if ( modifiedHandler && jQuery.isFunction( modifiedHandler ) ) {
|
||||||
|
modifiedHandler.guid = handler.guid;
|
||||||
|
handler = modifiedHandler;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init the event handler queue
|
// Init the event handler queue
|
||||||
|
@ -73,7 +78,7 @@ jQuery.event = {
|
||||||
// Check for a special event handler
|
// Check for a special event handler
|
||||||
// Only use addEventListener/attachEvent if the special
|
// Only use addEventListener/attachEvent if the special
|
||||||
// events handler returns false
|
// events handler returns false
|
||||||
if ( !this.special[ type ] || this.special[ type ].setup.call( elem, data, namespaces ) === false ) {
|
if ( !special.setup || special.setup.call( elem, data, namespaces ) === false ) {
|
||||||
// Bind the global event handler to the element
|
// Bind the global event handler to the element
|
||||||
if ( elem.addEventListener ) {
|
if ( elem.addEventListener ) {
|
||||||
elem.addEventListener( type, handle, false );
|
elem.addEventListener( type, handle, false );
|
||||||
|
@ -128,7 +133,8 @@ jQuery.event = {
|
||||||
var namespaces = type.split(".");
|
var namespaces = type.split(".");
|
||||||
type = namespaces.shift();
|
type = namespaces.shift();
|
||||||
var all = !namespaces.length,
|
var all = !namespaces.length,
|
||||||
namespace = new RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
|
namespace = new RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)"),
|
||||||
|
special = this.special[ type ] || {};
|
||||||
|
|
||||||
if ( events[ type ] ) {
|
if ( events[ type ] ) {
|
||||||
// remove the given handler for the given type
|
// remove the given handler for the given type
|
||||||
|
@ -145,8 +151,8 @@ jQuery.event = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( this.specialAll[ type ] ) {
|
if ( special.remove ) {
|
||||||
this.specialAll[ type ].teardown.call( elem, namespaces );
|
special.remove.call( elem, namespaces );
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove generic event handler if no more handlers exist
|
// remove generic event handler if no more handlers exist
|
||||||
|
@ -381,31 +387,20 @@ jQuery.event = {
|
||||||
// Make sure the ready event is setup
|
// Make sure the ready event is setup
|
||||||
setup: bindReady,
|
setup: bindReady,
|
||||||
teardown: function() {}
|
teardown: function() {}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
specialAll: {
|
|
||||||
live: {
|
live: {
|
||||||
setup: function( selector, namespaces ) {
|
add: function( proxy, data, namespaces ) {
|
||||||
jQuery.event.add( this, namespaces[0], liveHandler );
|
jQuery.extend( proxy, data || {} );
|
||||||
|
proxy.guid += data.selector + data.live;
|
||||||
|
jQuery.event.add( this, data.live, liveHandler );
|
||||||
},
|
},
|
||||||
|
|
||||||
teardown: function( namespaces ) {
|
teardown: function( namespaces ) {
|
||||||
if ( namespaces.length ) {
|
|
||||||
var remove = 0, name = new RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
|
|
||||||
|
|
||||||
jQuery.each( (jQuery.data(this, "events").live || {}), function() {
|
|
||||||
if ( name.test(this.type) ) {
|
|
||||||
remove++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if ( remove < 1 ) {
|
|
||||||
jQuery.event.remove( this, namespaces[0], liveHandler );
|
jQuery.event.remove( this, namespaces[0], liveHandler );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
jQuery.Event = function( src ){
|
jQuery.Event = function( src ){
|
||||||
|
@ -592,12 +587,10 @@ jQuery.fn.extend({
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
live: function( type, fn ) {
|
live: function( type, data, fn ) {
|
||||||
var proxy = jQuery.event.proxy( fn );
|
jQuery( this.context ).bind( liveConvert( type, this.selector ), {
|
||||||
proxy.guid += this.selector + type;
|
data: fn && data, selector: this.selector, live: type
|
||||||
|
}, fn || data );
|
||||||
jQuery( this.context ).bind( liveConvert( type, this.selector ), this.selector, proxy );
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -608,12 +601,11 @@ jQuery.fn.extend({
|
||||||
});
|
});
|
||||||
|
|
||||||
function liveHandler( event ) {
|
function liveHandler( event ) {
|
||||||
var check = new RegExp("(^|\\.)" + event.type + "(\\.|$)"),
|
var stop = true, elems = [];
|
||||||
stop = true, elems = [];
|
|
||||||
|
|
||||||
jQuery.each( jQuery.data( this, "events" ).live || [], function( i, fn ) {
|
jQuery.each( jQuery.data( this, "events" ).live || [], function( i, fn ) {
|
||||||
if ( check.test( fn.type ) ) {
|
if ( fn.live === event.type ) {
|
||||||
var elem = jQuery( event.target ).closest( fn.data )[0];
|
var elem = jQuery( event.target ).closest( fn.selector )[0];
|
||||||
if ( elem ) {
|
if ( elem ) {
|
||||||
elems.push({ elem: elem, fn: fn });
|
elems.push({ elem: elem, fn: fn });
|
||||||
}
|
}
|
||||||
|
@ -626,7 +618,8 @@ function liveHandler( event ) {
|
||||||
|
|
||||||
jQuery.each(elems, function() {
|
jQuery.each(elems, function() {
|
||||||
event.currentTarget = this.elem;
|
event.currentTarget = this.elem;
|
||||||
if ( this.fn.call( this.elem, event, this.fn.data ) === false ) {
|
event.data = this.fn.data
|
||||||
|
if ( this.fn.call( this.elem, event, this.fn.selector ) === false ) {
|
||||||
return (stop = false);
|
return (stop = false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -490,7 +490,7 @@ test("toggle(Function, Function, ...)", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test(".live()/.die()", function() {
|
test(".live()/.die()", function() {
|
||||||
expect(52);
|
expect(53);
|
||||||
|
|
||||||
var submit = 0, div = 0, livea = 0, liveb = 0;
|
var submit = 0, div = 0, livea = 0, liveb = 0;
|
||||||
|
|
||||||
|
@ -579,6 +579,9 @@ test(".live()/.die()", function() {
|
||||||
jQuery("#foo").trigger('click');
|
jQuery("#foo").trigger('click');
|
||||||
equals( clicked, 2, "die with a context");
|
equals( clicked, 2, "die with a context");
|
||||||
|
|
||||||
|
// Test binding with event data
|
||||||
|
jQuery("#foo").live("click", true, function(e){ equals( e.data, true, "live with event data" ); });
|
||||||
|
jQuery("#foo").trigger("click").die("click");
|
||||||
|
|
||||||
// Verify that return false prevents default action
|
// Verify that return false prevents default action
|
||||||
jQuery("#anchor2").live("click", function(){ return false; });
|
jQuery("#anchor2").live("click", function(){ return false; });
|
||||||
|
|
Loading…
Reference in a new issue