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 = {
handler.type = namespaces.slice().sort().join(".");
// Get the current list of functions bound to this event
var handlers = events[ type ];
if ( this.specialAll[ type ] ) {
this.specialAll[ type ].setup.call( elem, data, namespaces );
var handlers = events[ type ],
special = this.special[ type ] || {};
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
......@@ -73,7 +78,7 @@ jQuery.event = {
// Check for a special event handler
// Only use addEventListener/attachEvent if the special
// 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
if ( elem.addEventListener ) {
elem.addEventListener( type, handle, false );
......@@ -128,9 +133,10 @@ jQuery.event = {
var namespaces = type.split(".");
type = namespaces.shift();
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
if ( handler ) {
delete events[ type ][ handler.guid ];
......@@ -145,8 +151,8 @@ jQuery.event = {
}
}
if ( this.specialAll[ type ] ) {
this.specialAll[ type ].teardown.call( elem, namespaces );
if ( special.remove ) {
special.remove.call( elem, namespaces );
}
// remove generic event handler if no more handlers exist
......@@ -381,28 +387,17 @@ jQuery.event = {
// Make sure the ready event is setup
setup: bindReady,
teardown: function() {}
}
},
specialAll: {
},
live: {
setup: function( selector, namespaces ) {
jQuery.event.add( this, namespaces[0], liveHandler );
add: function( proxy, data, namespaces ) {
jQuery.extend( proxy, data || {} );
proxy.guid += data.selector + data.live;
jQuery.event.add( this, data.live, liveHandler );
},
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 );
}
}
teardown: function( namespaces ) {
jQuery.event.remove( this, namespaces[0], liveHandler );
}
}
}
......@@ -592,28 +587,25 @@ jQuery.fn.extend({
return this;
},
live: function( type, fn ) {
var proxy = jQuery.event.proxy( fn );
proxy.guid += this.selector + type;
jQuery( this.context ).bind( liveConvert( type, this.selector ), this.selector, proxy );
live: function( type, data, fn ) {
jQuery( this.context ).bind( liveConvert( type, this.selector ), {
data: fn && data, selector: this.selector, live: type
}, fn || data );
return this;
},
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;
}
});
function liveHandler( event ) {
var check = new RegExp("(^|\\.)" + event.type + "(\\.|$)"),
stop = true, elems = [];
var stop = true, elems = [];
jQuery.each( jQuery.data( this, "events" ).live || [], function( i, fn ) {
if ( check.test( fn.type ) ) {
var elem = jQuery( event.target ).closest( fn.data )[0];
if ( fn.live === event.type ) {
var elem = jQuery( event.target ).closest( fn.selector )[0];
if ( elem ) {
elems.push({ elem: elem, fn: fn });
}
......@@ -626,7 +618,8 @@ function liveHandler( event ) {
jQuery.each(elems, function() {
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);
}
});
......
......@@ -490,7 +490,7 @@ test("toggle(Function, Function, ...)", function() {
});
test(".live()/.die()", function() {
expect(52);
expect(53);
var submit = 0, div = 0, livea = 0, liveb = 0;
......@@ -579,6 +579,9 @@ test(".live()/.die()", function() {
jQuery("#foo").trigger('click');
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
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