Commit 71efbdd3 authored by Brandon Aaron's avatar Brandon Aaron

refactor specialAll into add and remove hooks for existing special events,...

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
parent 287ecdbf
...@@ -60,10 +60,15 @@ jQuery.event = { ...@@ -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 ] ) {
this.specialAll[ type ].setup.call( elem, data, namespaces ); if ( special.add ) {
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 = { ...@@ -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,9 +133,10 @@ jQuery.event = { ...@@ -128,9 +133,10 @@ 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
if ( handler ) { if ( handler ) {
delete events[ type ][ handler.guid ]; delete events[ type ][ handler.guid ];
...@@ -145,8 +151,8 @@ jQuery.event = { ...@@ -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,28 +387,17 @@ jQuery.event = { ...@@ -381,28 +387,17 @@ 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 ) {
if ( namespaces.length ) { teardown: function( namespaces ) {
var remove = 0, name = new RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)"); jQuery.event.remove( this, namespaces[0], liveHandler );
jQuery.each( (jQuery.data(this, "events").live || {}), function() {
if ( name.test(this.type) ) {
remove++;
}
});
if ( remove < 1 ) {
jQuery.event.remove( this, namespaces[0], liveHandler );
}
}
} }
} }
} }
...@@ -592,28 +587,25 @@ jQuery.fn.extend({ ...@@ -592,28 +587,25 @@ 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;
}, },
die: function( type, fn ) { die: function( type, fn ) {
jQuery( this.context ).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null ); jQuery( this.context ).unbind( liveConvert( type, this.selector ), fn ? { guid: fn.guid + this.selector + type } : null );
return this; return this;
} }
}); });
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 ) { ...@@ -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() { ...@@ -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() { ...@@ -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; });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment