// Event object or event type
var type = event.type || event,
namespaces = [],
- cache, exclusive, i, cur, old, ontype, special, doc, eventPath, bubbleType,
- addHandlers = function( elem, type ) {
- // Defer getting handler so we don't waste time in case propagation is stopped
- if ( (jQuery._data( elem, "events" ) || {})[ type ] ) {
- eventPath.push({ elem: elem, type: type /*, handler: jQuery._data( elem, "handle" ) */ });
- }
- // IE doesn't like method names with a colon (#3533, #8272)
- if ( ontype && jQuery.acceptData( elem ) && elem[ ontype ] ) {
- eventPath.push({ elem: elem, type: type, handler: elem[ ontype ] });
- }
- };
+ cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;
if ( type.indexOf( "!" ) >= 0 ) {
// Exclusive events trigger only for the exact event (no namespaces)
// triggerHandler() and global events don't bubble or run the default action
if ( onlyHandlers || !elem ) {
event.preventDefault();
- event.stopPropagation();
}
// Handle a global trigger
// TODO: Stop taunting the data cache; remove global events and always attach to document
cache = jQuery.cache;
+ event.stopPropagation();
for ( i in cache ) {
if ( cache[ i ].events && cache[ i ].events[ type ] ) {
jQuery.event.trigger( event, data, cache[ i ].handle.elem );
// Determine event propagation path in advance, per W3C events spec (#9951)
// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
- // Always fire handlers for the target, even if prop is stopped in advance
- eventPath = [];
- addHandlers( elem, special.bindType || type );
- doc = elem.ownerDocument;
- if ( doc && !special.noBubble && !jQuery.isWindow( elem ) & !event.isPropagationStopped() ) {
+ eventPath = [[ elem, special.bindType || type ]];
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
bubbleType = special.delegateType || type;
+ old = null;
for ( cur = elem.parentNode; cur; cur = cur.parentNode ) {
- addHandlers( cur, bubbleType );
+ eventPath.push([ cur, bubbleType ]);
+ old = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( old && old === elem.ownerDocument ) {
+ eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
}
- addHandlers( doc.defaultView || doc.parentWindow || window, bubbleType );
}
- // Bubble up the DOM tree
+ // Fire handlers on the event path
for ( i = 0; i < eventPath.length; i++ ) {
- cur = eventPath[ i ];
- event.type = cur.type;
- ( cur.handler || jQuery._data( cur.elem, "handle" ) ).apply( cur.elem, data );
+
+ cur = eventPath[i][0];
+ event.type = eventPath[i][1];
+
+ handle = (jQuery._data( cur, "events" ) || {})[ event.type ] && jQuery._data( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+ handle = ontype && cur[ ontype ];
+ if ( handle && jQuery.acceptData( cur ) ) {
+ handle.apply( cur, data );
+ }
+
if ( event.isPropagationStopped() ) {
break;
}
});
-/*
-Removed because Chrome 13 snaps/crashes on this 2011-09-07
-
test("Handler changes and .trigger() order", function() {
expect(1);
var markup = jQuery(
- '<div><p><b class="a">b</b></p></div>'
- ).appendTo( "body" );
+ '<div><div><p><span><b class="a">b</b></span></p></div></div>'
+ ),
+ path = "";
- var path = "";
- jQuery( "b" ).parents().bind( "click", function(e){
- path += this.nodeName.toLowerCase() + " ";
- // Should not change the event triggering order
- $(this).parent().remove();
- });
+ markup
+ .find( "*" ).andSelf().on( "click", function( e ) {
+ path += this.nodeName.toLowerCase() + " ";
+ })
+ .filter( "b" ).on( "click", function( e ) {
+ // Removing span should not stop propagation to original parents
+ if ( e.target === this ) {
+ jQuery(this).parent().remove();
+ }
+ });
markup.find( "b" ).trigger( "click" );
- equals( path, "p div body html ", "Delivered all events" )
+ equals( path, "b p div div ", "Delivered all events" );
markup.remove();
});
-*/
test("bind(), with data", function() {
expect(4);
$parent.unbind().remove();
});
+test(".trigger() bubbling on disconnected elements (#10489)", function() {
+ expect(2);
+
+ jQuery( window ).on( "click", function(){
+ ok( false, "click fired on window" );
+ });
+
+ jQuery( "<div><p>hi</p></div>" )
+ .on( "click", function() {
+ ok( true, "click fired on div" );
+ })
+ .find( "p" )
+ .on( "click", function() {
+ ok( true, "click fired on p" );
+ })
+ .click()
+ .off( "click" )
+ .end()
+ .off( "click" )
+ .remove();
+
+ jQuery( window ).off( "click" );
+});
+
test("jQuery.Event( type, props )", function() {
expect(5);