diff options
author | Dave Methvin <dave.methvin@gmail.com> | 2011-10-13 16:30:40 -0400 |
---|---|---|
committer | Dave Methvin <dave.methvin@gmail.com> | 2011-10-13 16:30:40 -0400 |
commit | 0a3cab8d4916045da51d843bdb6385c110ab3163 (patch) | |
tree | f04e759f4c6eb1904ce852fa3de44efb18c03b62 /src | |
parent | 7bef99e94d0fa6a9885403760e30a59ef32e96a4 (diff) | |
download | jquery-0a3cab8d4916045da51d843bdb6385c110ab3163.tar.gz jquery-0a3cab8d4916045da51d843bdb6385c110ab3163.zip |
Fix #10489. Disconnected elements don't bubble to document.
Diffstat (limited to 'src')
-rw-r--r-- | src/event.js | 50 |
1 files changed, 27 insertions, 23 deletions
diff --git a/src/event.js b/src/event.js index 17872f02d..a475a25ea 100644 --- a/src/event.js +++ b/src/event.js @@ -261,17 +261,7 @@ jQuery.event = { // 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) @@ -310,7 +300,6 @@ jQuery.event = { // triggerHandler() and global events don't bubble or run the default action if ( onlyHandlers || !elem ) { event.preventDefault(); - event.stopPropagation(); } // Handle a global trigger @@ -318,6 +307,7 @@ jQuery.event = { // 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 ); @@ -344,23 +334,37 @@ jQuery.event = { // 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; } |