Skip to content

Commit be2407e

Browse files
committed
Rewrote the live event handling to use the new event logic. Also added in support for live namespaced events. Fixes #5945.
1 parent 1047577 commit be2407e

File tree

2 files changed

+152
-91
lines changed

2 files changed

+152
-91
lines changed

src/event.js

Lines changed: 84 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
var fcleanup = function( nm ) {
2-
return nm.replace(/[^\w\s\.\|`]/g, function( ch ) {
3-
return "\\" + ch;
4-
});
5-
};
1+
var rnamespaces = /\.(.*)$/,
2+
fcleanup = function( nm ) {
3+
return nm.replace(/[^\w\s\.\|`]/g, function( ch ) {
4+
return "\\" + ch;
5+
});
6+
};
67

78
/*
89
* A number of helper functions used for managing events.
@@ -24,6 +25,13 @@ jQuery.event = {
2425
elem = window;
2526
}
2627

28+
var handleObjIn, handleObj;
29+
30+
if ( handler.handler ) {
31+
handleObjIn = handler;
32+
handler = handleObjIn.handler;
33+
}
34+
2735
// Make sure that the function being executed has a unique ID
2836
if ( !handler.guid ) {
2937
handler.guid = jQuery.guid++;
@@ -62,12 +70,9 @@ jQuery.event = {
6270
var type, i = 0, namespaces;
6371

6472
while ( (type = types[ i++ ]) ) {
65-
var handleObj = {
66-
handler: handler,
67-
data: data,
68-
namespace: "",
69-
guid: handler.guid
70-
};
73+
handleObj = handleObjIn ?
74+
jQuery.extend({}, handleObjIn) :
75+
{ handler: handler, data: data };
7176

7277
// Namespaced event handlers
7378
if ( type.indexOf(".") > -1 ) {
@@ -77,9 +82,11 @@ jQuery.event = {
7782

7883
} else {
7984
namespaces = [];
85+
handleObj.namespace = "";
8086
}
8187

8288
handleObj.type = type;
89+
handleObj.guid = handler.guid;
8390

8491
// Get the current list of functions bound to this event
8592
var handlers = events[ type ],
@@ -92,7 +99,7 @@ jQuery.event = {
9299
// Check for a special event handler
93100
// Only use addEventListener/attachEvent if the special
94101
// events handler returns false
95-
if ( !special.setup || special.setup.call( elem, data, namespaces, handler ) === false ) {
102+
if ( !special.setup || special.setup.call( elem, data, namespaces ) === false ) {
96103
// Bind the global event handler to the element
97104
if ( elem.addEventListener ) {
98105
elem.addEventListener( type, eventHandle, false );
@@ -106,7 +113,7 @@ jQuery.event = {
106113
if ( special.add ) {
107114
special.add.call( elem, handleObj );
108115
}
109-
116+
110117
// Add the function to the element's handler list
111118
handlers.push( handleObj );
112119

@@ -198,14 +205,12 @@ jQuery.event = {
198205
if ( handler.guid === handleObj.guid ) {
199206
// remove the given handler for the given type
200207
if ( all || namespace.test( handleObj.namespace ) ) {
201-
fn = handleObj.handler;
202-
203208
if ( pos == null ) {
204209
eventType.splice( j--, 1 );
205210
}
206211

207212
if ( special.remove ) {
208-
special.remove.call( elem, namespaces, handleObj );
213+
special.remove.call( elem, handleObj );
209214
}
210215
}
211216

@@ -380,6 +385,7 @@ jQuery.event = {
380385
// So that we can later remove it
381386
event.handler = handleObj.handler;
382387
event.data = handleObj.data;
388+
event.handleObj = handleObj;
383389

384390
var ret = handleObj.handler.apply( this, arguments );
385391

@@ -473,33 +479,28 @@ jQuery.event = {
473479
},
474480

475481
live: {
476-
add: function( proxy, data, namespaces, live ) {
477-
jQuery.extend( proxy, data || {} );
478-
479-
proxy.guid += data.selector + data.live;
480-
data.liveProxy = proxy;
481-
482-
jQuery.event.add( this, data.live, liveHandler, data );
483-
482+
add: function( handleObj ) {
483+
jQuery.event.add( this, handleObj.origType, jQuery.extend({}, handleObj, {handler: liveHandler}) );
484484
},
485485

486-
remove: function( namespaces ) {
487-
if ( namespaces.length ) {
488-
var remove = 0, name = new RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
489-
490-
jQuery.each( (jQuery.data(this, "events").live || {}), function() {
491-
if ( name.test(this.type) ) {
492-
remove++;
493-
}
494-
});
495-
496-
if ( remove < 1 ) {
497-
jQuery.event.remove( this, namespaces[0], liveHandler );
486+
remove: function( handleObj ) {
487+
var remove = true,
488+
type = handleObj.origType.replace(rnamespaces, "");
489+
490+
jQuery.each( jQuery.data(this, "events").live || [], function() {
491+
if ( type === this.origType.replace(rnamespaces, "") ) {
492+
remove = false;
493+
return false;
498494
}
495+
});
496+
497+
if ( remove ) {
498+
jQuery.event.remove( this, handleObj.origType, liveHandler );
499499
}
500-
},
501-
special: {}
500+
}
501+
502502
},
503+
503504
beforeunload: {
504505
setup: function( data, namespaces, fn ) {
505506
// We only want to do this special case on windows
@@ -918,7 +919,7 @@ jQuery.fn.extend({
918919

919920
jQuery.each(["live", "die"], function( i, name ) {
920921
jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
921-
var type, i = 0,
922+
var type, i = 0, match, namespaces,
922923
selector = origSelector || this.selector,
923924
context = origSelector ? this : jQuery( this.context );
924925

@@ -927,23 +928,34 @@ jQuery.each(["live", "die"], function( i, name ) {
927928
data = undefined;
928929
}
929930

930-
types = (types || "").split( /\s+/ );
931+
types = (types || "").split(" ");
931932

932933
while ( (type = types[ i++ ]) != null ) {
934+
match = rnamespaces.exec( type );
935+
namespaces = "";
936+
937+
if ( match ) {
938+
namespaces = match[0];
939+
type = type.replace( rnamespaces, "" );
940+
}
941+
933942
type = type === "focus" ? "focusin" : // focus --> focusin
934943
type === "blur" ? "focusout" : // blur --> focusout
935-
type === "hover" ? types.push("mouseleave") && "mouseenter" : // hover support
944+
type === "hover" ? types.push("mouseleave" + namespaces) && "mouseenter" : // hover support
936945
type;
937-
946+
947+
type += namespaces;
948+
938949
if ( name === "live" ) {
939950
// bind live handler
940-
context.bind( liveConvert( type, selector ), {
941-
data: data, selector: selector, live: type
942-
}, fn );
951+
context.each(function(){
952+
jQuery.event.add( this, liveConvert( type, selector ),
953+
{ data: data, selector: selector, handler: fn, origType: type, origHandler: fn } );
954+
});
943955

944956
} else {
945957
// unbind live handler
946-
context.unbind( liveConvert( type, selector ), fn ? { guid: fn.guid + selector + type } : null );
958+
context.unbind( liveConvert( type, selector ), fn );
947959
}
948960
}
949961

@@ -953,45 +965,46 @@ jQuery.each(["live", "die"], function( i, name ) {
953965

954966
function liveHandler( event ) {
955967
var stop, elems = [], selectors = [], args = arguments,
956-
related, match, fn, elem, j, i, l, data,
957-
live = jQuery.extend({}, jQuery.data( this, "events" ).live);
968+
related, match, handleObj, elem, j, i, l, data,
969+
events = jQuery.data( this, "events" );
958970

959971
// Make sure we avoid non-left-click bubbling in Firefox (#3861)
960-
if ( event.button && event.type === "click" ) {
972+
if ( event.liveFired === this || !events || event.button && event.type === "click" ) {
961973
return;
962974
}
963975

964-
for ( j in live ) {
965-
fn = live[j];
966-
if ( fn.live === event.type ||
967-
fn.altLive && jQuery.inArray(event.type, fn.altLive) > -1 ) {
976+
event.liveFired = this;
977+
978+
var live = events.live.slice(0);
979+
980+
for ( j = 0; j < live.length; j++ ) {
981+
handleObj = live[j];
982+
983+
if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
984+
selectors.push( handleObj.selector );
968985

969-
data = fn.data;
970-
if ( !(data.beforeFilter && data.beforeFilter[event.type] &&
971-
!data.beforeFilter[event.type](event)) ) {
972-
selectors.push( fn.selector );
973-
}
974986
} else {
975-
delete live[j];
987+
live.splice( j--, 1 );
976988
}
977989
}
978990

979991
match = jQuery( event.target ).closest( selectors, event.currentTarget );
980992

981993
for ( i = 0, l = match.length; i < l; i++ ) {
982-
for ( j in live ) {
983-
fn = live[j];
984-
elem = match[i].elem;
985-
related = null;
994+
for ( j = 0; j < live.length; j++ ) {
995+
handleObj = live[j];
996+
997+
if ( match[i].selector === handleObj.selector ) {
998+
elem = match[i].elem;
999+
related = null;
9861000

987-
if ( match[i].selector === fn.selector ) {
9881001
// Those two events require additional checking
989-
if ( fn.live === "mouseenter" || fn.live === "mouseleave" ) {
990-
related = jQuery( event.relatedTarget ).closest( fn.selector )[0];
1002+
if ( handleObj.origType === "mouseenter" || handleObj.origType === "mouseleave" ) {
1003+
related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
9911004
}
9921005

9931006
if ( !related || related !== elem ) {
994-
elems.push({ elem: elem, fn: fn });
1007+
elems.push({ elem: elem, handleObj: handleObj });
9951008
}
9961009
}
9971010
}
@@ -1000,8 +1013,10 @@ function liveHandler( event ) {
10001013
for ( i = 0, l = elems.length; i < l; i++ ) {
10011014
match = elems[i];
10021015
event.currentTarget = match.elem;
1003-
event.data = match.fn.data;
1004-
if ( match.fn.apply( match.elem, args ) === false ) {
1016+
event.data = match.handleObj.data;
1017+
event.handleObj = match.handleObj;
1018+
1019+
if ( match.handleObj.origHandler.apply( match.elem, args ) === false ) {
10051020
stop = false;
10061021
break;
10071022
}

0 commit comments

Comments
 (0)