mirror of
https://github.com/jquery/jquery.git
synced 2024-11-23 02:54:22 +00:00
Switch from recursion to iteration for event triggering. Move event-name namespace processing out of event handler, since it has to always go through trigger.
This commit is contained in:
parent
e0856738e6
commit
bfa32317d2
120
src/event.js
120
src/event.js
@ -277,13 +277,12 @@ jQuery.event = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// bubbling is internal
|
trigger: function( event, data, elem ) {
|
||||||
trigger: function( event, data, elem /*, bubbling */ ) {
|
|
||||||
// Event object or event type
|
// Event object or event type
|
||||||
var type = event.type || event,
|
var type = event.type || event,
|
||||||
bubbling = arguments[3];
|
bubbling = arguments[3],
|
||||||
|
namespaces = [];
|
||||||
|
|
||||||
if ( !bubbling ) {
|
|
||||||
event = typeof event === "object" ?
|
event = typeof event === "object" ?
|
||||||
// jQuery.Event object
|
// jQuery.Event object
|
||||||
event[ jQuery.expando ] ? event :
|
event[ jQuery.expando ] ? event :
|
||||||
@ -293,9 +292,18 @@ jQuery.event = {
|
|||||||
jQuery.Event(type);
|
jQuery.Event(type);
|
||||||
|
|
||||||
if ( type.indexOf("!") >= 0 ) {
|
if ( type.indexOf("!") >= 0 ) {
|
||||||
|
// Exclusive events trigger only for the bare event type (no namespaces)
|
||||||
event.type = type = type.slice(0, -1);
|
event.type = type = type.slice(0, -1);
|
||||||
event.exclusive = true;
|
event.exclusive = true;
|
||||||
}
|
}
|
||||||
|
if ( type.indexOf(".") >= 0 ) {
|
||||||
|
// Namespaced trigger; create a regexp to match event type in handle()
|
||||||
|
namespaces = type.split(".");
|
||||||
|
event.type = type = namespaces.shift();
|
||||||
|
namespaces.sort();
|
||||||
|
}
|
||||||
|
event.namespace = namespaces.join(".");
|
||||||
|
event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)");
|
||||||
|
|
||||||
// Handle a global trigger
|
// Handle a global trigger
|
||||||
if ( !elem ) {
|
if ( !elem ) {
|
||||||
@ -317,13 +325,12 @@ jQuery.event = {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle triggering a single element
|
|
||||||
|
|
||||||
// don't do events on text and comment nodes
|
// don't do events on text and comment nodes
|
||||||
if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
|
if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
|
||||||
return undefined;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up in case it is reused
|
// Clean up in case it is reused
|
||||||
@ -333,62 +340,53 @@ jQuery.event = {
|
|||||||
// Clone the incoming data, if any
|
// Clone the incoming data, if any
|
||||||
data = jQuery.makeArray( data );
|
data = jQuery.makeArray( data );
|
||||||
data.unshift( event );
|
data.unshift( event );
|
||||||
}
|
|
||||||
|
|
||||||
event.currentTarget = elem;
|
// Always fire on the current element, e.g. triggerHandler or global trigger
|
||||||
|
var cur = elem;
|
||||||
// Trigger the event, it is assumed that "handle" is a function
|
do {
|
||||||
var handle = jQuery._data( elem, "handle" );
|
var handle = jQuery._data( cur, "handle" );
|
||||||
|
|
||||||
|
event.currentTarget = cur;
|
||||||
if ( handle ) {
|
if ( handle ) {
|
||||||
handle.apply( elem, data );
|
handle.apply( cur, data );
|
||||||
}
|
}
|
||||||
|
|
||||||
var parent = elem.parentNode || elem.ownerDocument;
|
// Trigger an inline bound script; IE dies on special-char event names
|
||||||
|
try {
|
||||||
// Trigger an inline bound script
|
if ( jQuery.acceptData( cur ) && cur[ "on" + type ] && cur[ "on" + type ].apply( cur, data ) === false ) {
|
||||||
try {
|
|
||||||
if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
|
|
||||||
if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
|
|
||||||
event.result = false;
|
event.result = false;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
} catch ( ieError ) {}
|
||||||
|
|
||||||
// prevent IE from throwing an error for some elements with some event types, see #3533
|
cur = cur.parentNode || cur.ownerDocument;
|
||||||
} catch (inlineError) {}
|
} while ( cur && !event.isPropagationStopped() );
|
||||||
|
|
||||||
if ( !event.isPropagationStopped() && parent ) {
|
// If nobody prevented the default action, do it now
|
||||||
jQuery.event.trigger( event, data, parent, true );
|
if ( !event.isDefaultPrevented() ) {
|
||||||
|
|
||||||
} else if ( !event.isDefaultPrevented() ) {
|
|
||||||
var old,
|
var old,
|
||||||
target = event.target,
|
special = jQuery.event.special[ type ] || {};
|
||||||
targetType = type.replace( rnamespaces, "" ),
|
|
||||||
isClick = jQuery.nodeName( target, "a" ) && targetType === "click",
|
|
||||||
special = jQuery.event.special[ targetType ] || {};
|
|
||||||
|
|
||||||
if ( (!special._default || special._default.call( elem, event ) === false) &&
|
if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) &&
|
||||||
!isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
|
!(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
|
||||||
|
|
||||||
|
// IE may die here on non-alpha event names or hidden elements (#3533)
|
||||||
try {
|
try {
|
||||||
if ( target[ targetType ] ) {
|
if ( elem[ type ] ) {
|
||||||
// Make sure that we don't accidentally re-trigger the onFOO events
|
// Don't accidentally re-trigger the onFOO events
|
||||||
old = target[ "on" + targetType ];
|
old = elem[ "on" + type ];
|
||||||
|
|
||||||
if ( old ) {
|
if ( old ) {
|
||||||
target[ "on" + targetType ] = null;
|
elem[ "on" + type ] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
jQuery.event.triggered = event.type;
|
jQuery.event.triggered = event.type;
|
||||||
target[ targetType ]();
|
elem[ type ]();
|
||||||
}
|
}
|
||||||
|
} catch ( ieError ) {}
|
||||||
// prevent IE from throwing an error for some elements with some event types, see #3533
|
|
||||||
} catch (triggerError) {}
|
|
||||||
|
|
||||||
if ( old ) {
|
if ( old ) {
|
||||||
target[ "on" + targetType ] = old;
|
elem[ "on" + type ] = old;
|
||||||
}
|
}
|
||||||
|
|
||||||
jQuery.event.triggered = undefined;
|
jQuery.event.triggered = undefined;
|
||||||
@ -397,38 +395,24 @@ jQuery.event = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
handle: function( event ) {
|
handle: function( event ) {
|
||||||
var all, handlers, namespaces, namespace_re, events,
|
// It's rare to arrive without handlers to call, so do all setup here.
|
||||||
namespace_sort = [],
|
// Copy the handler list since a called handler may add/remove events.
|
||||||
|
event = jQuery.event.fix( event || window.event );
|
||||||
|
var events = jQuery._data( this, "events" ),
|
||||||
|
handlers = ((events || {})[ event.type ] || []).slice(0),
|
||||||
|
all_handlers = !event.exclusive && !event.namespace,
|
||||||
args = jQuery.makeArray( arguments );
|
args = jQuery.makeArray( arguments );
|
||||||
|
|
||||||
event = args[0] = jQuery.event.fix( event || window.event );
|
// Use the fix-ed Event rather than the (read-only) native event
|
||||||
|
args[0] = event;
|
||||||
event.currentTarget = this;
|
event.currentTarget = this;
|
||||||
|
|
||||||
// Namespaced event handlers
|
|
||||||
all = event.type.indexOf(".") < 0 && !event.exclusive;
|
|
||||||
|
|
||||||
if ( !all ) {
|
|
||||||
namespaces = event.type.split(".");
|
|
||||||
event.type = namespaces.shift();
|
|
||||||
namespace_sort = namespaces.slice(0).sort();
|
|
||||||
namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
|
|
||||||
}
|
|
||||||
|
|
||||||
event.namespace = event.namespace || namespace_sort.join(".");
|
|
||||||
|
|
||||||
events = jQuery._data(this, "events");
|
|
||||||
|
|
||||||
handlers = (events || {})[ event.type ];
|
|
||||||
|
|
||||||
if ( events && handlers ) {
|
|
||||||
// Clone the handlers to prevent manipulation
|
|
||||||
handlers = handlers.slice(0);
|
|
||||||
|
|
||||||
for ( var j = 0, l = handlers.length; j < l; j++ ) {
|
for ( var j = 0, l = handlers.length; j < l; j++ ) {
|
||||||
var handleObj = handlers[ j ];
|
var handleObj = handlers[ j ];
|
||||||
|
|
||||||
// Filter the functions by class
|
// Triggered event must 1) be non-exclusive and have no namespace, or
|
||||||
if ( all || namespace_re.test( handleObj.namespace ) ) {
|
// 2) have namespace(s) a subset or equal to those in the bound event.
|
||||||
|
if ( all_handlers || event.namespace_re.test( handleObj.namespace ) ) {
|
||||||
// Pass in a reference to the handler function itself
|
// Pass in a reference to the handler function itself
|
||||||
// So that we can later remove it
|
// So that we can later remove it
|
||||||
event.handler = handleObj.handler;
|
event.handler = handleObj.handler;
|
||||||
@ -450,8 +434,6 @@ jQuery.event = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return event.result;
|
return event.result;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user