event.js (27927B)
1 define( [ 2 "./core", 3 "./var/document", 4 "./var/documentElement", 5 "./var/isFunction", 6 "./var/rnothtmlwhite", 7 "./var/rcheckableType", 8 "./var/slice", 9 "./data/var/acceptData", 10 "./data/var/dataPriv", 11 "./core/nodeName", 12 13 "./core/init", 14 "./selector" 15 ], function( jQuery, document, documentElement, isFunction, rnothtmlwhite, 16 rcheckableType, slice, acceptData, dataPriv, nodeName ) { 17 18 "use strict"; 19 20 var rtypenamespace = /^([^.]*)(?:\.(.+)|)/; 21 22 function returnTrue() { 23 return true; 24 } 25 26 function returnFalse() { 27 return false; 28 } 29 30 function on( elem, types, selector, data, fn, one ) { 31 var origFn, type; 32 33 // Types can be a map of types/handlers 34 if ( typeof types === "object" ) { 35 36 // ( types-Object, selector, data ) 37 if ( typeof selector !== "string" ) { 38 39 // ( types-Object, data ) 40 data = data || selector; 41 selector = undefined; 42 } 43 for ( type in types ) { 44 on( elem, type, selector, data, types[ type ], one ); 45 } 46 return elem; 47 } 48 49 if ( data == null && fn == null ) { 50 51 // ( types, fn ) 52 fn = selector; 53 data = selector = undefined; 54 } else if ( fn == null ) { 55 if ( typeof selector === "string" ) { 56 57 // ( types, selector, fn ) 58 fn = data; 59 data = undefined; 60 } else { 61 62 // ( types, data, fn ) 63 fn = data; 64 data = selector; 65 selector = undefined; 66 } 67 } 68 if ( fn === false ) { 69 fn = returnFalse; 70 } else if ( !fn ) { 71 return elem; 72 } 73 74 if ( one === 1 ) { 75 origFn = fn; 76 fn = function( event ) { 77 78 // Can use an empty set, since event contains the info 79 jQuery().off( event ); 80 return origFn.apply( this, arguments ); 81 }; 82 83 // Use same guid so caller can remove using origFn 84 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); 85 } 86 return elem.each( function() { 87 jQuery.event.add( this, types, fn, data, selector ); 88 } ); 89 } 90 91 /* 92 * Helper functions for managing events -- not part of the public interface. 93 * Props to Dean Edwards' addEvent library for many of the ideas. 94 */ 95 jQuery.event = { 96 97 global: {}, 98 99 add: function( elem, types, handler, data, selector ) { 100 101 var handleObjIn, eventHandle, tmp, 102 events, t, handleObj, 103 special, handlers, type, namespaces, origType, 104 elemData = dataPriv.get( elem ); 105 106 // Only attach events to objects that accept data 107 if ( !acceptData( elem ) ) { 108 return; 109 } 110 111 // Caller can pass in an object of custom data in lieu of the handler 112 if ( handler.handler ) { 113 handleObjIn = handler; 114 handler = handleObjIn.handler; 115 selector = handleObjIn.selector; 116 } 117 118 // Ensure that invalid selectors throw exceptions at attach time 119 // Evaluate against documentElement in case elem is a non-element node (e.g., document) 120 if ( selector ) { 121 jQuery.find.matchesSelector( documentElement, selector ); 122 } 123 124 // Make sure that the handler has a unique ID, used to find/remove it later 125 if ( !handler.guid ) { 126 handler.guid = jQuery.guid++; 127 } 128 129 // Init the element's event structure and main handler, if this is the first 130 if ( !( events = elemData.events ) ) { 131 events = elemData.events = Object.create( null ); 132 } 133 if ( !( eventHandle = elemData.handle ) ) { 134 eventHandle = elemData.handle = function( e ) { 135 136 // Discard the second event of a jQuery.event.trigger() and 137 // when an event is called after a page has unloaded 138 return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? 139 jQuery.event.dispatch.apply( elem, arguments ) : undefined; 140 }; 141 } 142 143 // Handle multiple events separated by a space 144 types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; 145 t = types.length; 146 while ( t-- ) { 147 tmp = rtypenamespace.exec( types[ t ] ) || []; 148 type = origType = tmp[ 1 ]; 149 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); 150 151 // There *must* be a type, no attaching namespace-only handlers 152 if ( !type ) { 153 continue; 154 } 155 156 // If event changes its type, use the special event handlers for the changed type 157 special = jQuery.event.special[ type ] || {}; 158 159 // If selector defined, determine special event api type, otherwise given type 160 type = ( selector ? special.delegateType : special.bindType ) || type; 161 162 // Update special based on newly reset type 163 special = jQuery.event.special[ type ] || {}; 164 165 // handleObj is passed to all event handlers 166 handleObj = jQuery.extend( { 167 type: type, 168 origType: origType, 169 data: data, 170 handler: handler, 171 guid: handler.guid, 172 selector: selector, 173 needsContext: selector && jQuery.expr.match.needsContext.test( selector ), 174 namespace: namespaces.join( "." ) 175 }, handleObjIn ); 176 177 // Init the event handler queue if we're the first 178 if ( !( handlers = events[ type ] ) ) { 179 handlers = events[ type ] = []; 180 handlers.delegateCount = 0; 181 182 // Only use addEventListener if the special events handler returns false 183 if ( !special.setup || 184 special.setup.call( elem, data, namespaces, eventHandle ) === false ) { 185 186 if ( elem.addEventListener ) { 187 elem.addEventListener( type, eventHandle ); 188 } 189 } 190 } 191 192 if ( special.add ) { 193 special.add.call( elem, handleObj ); 194 195 if ( !handleObj.handler.guid ) { 196 handleObj.handler.guid = handler.guid; 197 } 198 } 199 200 // Add to the element's handler list, delegates in front 201 if ( selector ) { 202 handlers.splice( handlers.delegateCount++, 0, handleObj ); 203 } else { 204 handlers.push( handleObj ); 205 } 206 207 // Keep track of which events have ever been used, for event optimization 208 jQuery.event.global[ type ] = true; 209 } 210 211 }, 212 213 // Detach an event or set of events from an element 214 remove: function( elem, types, handler, selector, mappedTypes ) { 215 216 var j, origCount, tmp, 217 events, t, handleObj, 218 special, handlers, type, namespaces, origType, 219 elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); 220 221 if ( !elemData || !( events = elemData.events ) ) { 222 return; 223 } 224 225 // Once for each type.namespace in types; type may be omitted 226 types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; 227 t = types.length; 228 while ( t-- ) { 229 tmp = rtypenamespace.exec( types[ t ] ) || []; 230 type = origType = tmp[ 1 ]; 231 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); 232 233 // Unbind all events (on this namespace, if provided) for the element 234 if ( !type ) { 235 for ( type in events ) { 236 jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); 237 } 238 continue; 239 } 240 241 special = jQuery.event.special[ type ] || {}; 242 type = ( selector ? special.delegateType : special.bindType ) || type; 243 handlers = events[ type ] || []; 244 tmp = tmp[ 2 ] && 245 new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); 246 247 // Remove matching events 248 origCount = j = handlers.length; 249 while ( j-- ) { 250 handleObj = handlers[ j ]; 251 252 if ( ( mappedTypes || origType === handleObj.origType ) && 253 ( !handler || handler.guid === handleObj.guid ) && 254 ( !tmp || tmp.test( handleObj.namespace ) ) && 255 ( !selector || selector === handleObj.selector || 256 selector === "**" && handleObj.selector ) ) { 257 handlers.splice( j, 1 ); 258 259 if ( handleObj.selector ) { 260 handlers.delegateCount--; 261 } 262 if ( special.remove ) { 263 special.remove.call( elem, handleObj ); 264 } 265 } 266 } 267 268 // Remove generic event handler if we removed something and no more handlers exist 269 // (avoids potential for endless recursion during removal of special event handlers) 270 if ( origCount && !handlers.length ) { 271 if ( !special.teardown || 272 special.teardown.call( elem, namespaces, elemData.handle ) === false ) { 273 274 jQuery.removeEvent( elem, type, elemData.handle ); 275 } 276 277 delete events[ type ]; 278 } 279 } 280 281 // Remove data and the expando if it's no longer used 282 if ( jQuery.isEmptyObject( events ) ) { 283 dataPriv.remove( elem, "handle events" ); 284 } 285 }, 286 287 dispatch: function( nativeEvent ) { 288 289 var i, j, ret, matched, handleObj, handlerQueue, 290 args = new Array( arguments.length ), 291 292 // Make a writable jQuery.Event from the native event object 293 event = jQuery.event.fix( nativeEvent ), 294 295 handlers = ( 296 dataPriv.get( this, "events" ) || Object.create( null ) 297 )[ event.type ] || [], 298 special = jQuery.event.special[ event.type ] || {}; 299 300 // Use the fix-ed jQuery.Event rather than the (read-only) native event 301 args[ 0 ] = event; 302 303 for ( i = 1; i < arguments.length; i++ ) { 304 args[ i ] = arguments[ i ]; 305 } 306 307 event.delegateTarget = this; 308 309 // Call the preDispatch hook for the mapped type, and let it bail if desired 310 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { 311 return; 312 } 313 314 // Determine handlers 315 handlerQueue = jQuery.event.handlers.call( this, event, handlers ); 316 317 // Run delegates first; they may want to stop propagation beneath us 318 i = 0; 319 while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { 320 event.currentTarget = matched.elem; 321 322 j = 0; 323 while ( ( handleObj = matched.handlers[ j++ ] ) && 324 !event.isImmediatePropagationStopped() ) { 325 326 // If the event is namespaced, then each handler is only invoked if it is 327 // specially universal or its namespaces are a superset of the event's. 328 if ( !event.rnamespace || handleObj.namespace === false || 329 event.rnamespace.test( handleObj.namespace ) ) { 330 331 event.handleObj = handleObj; 332 event.data = handleObj.data; 333 334 ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || 335 handleObj.handler ).apply( matched.elem, args ); 336 337 if ( ret !== undefined ) { 338 if ( ( event.result = ret ) === false ) { 339 event.preventDefault(); 340 event.stopPropagation(); 341 } 342 } 343 } 344 } 345 } 346 347 // Call the postDispatch hook for the mapped type 348 if ( special.postDispatch ) { 349 special.postDispatch.call( this, event ); 350 } 351 352 return event.result; 353 }, 354 355 handlers: function( event, handlers ) { 356 var i, handleObj, sel, matchedHandlers, matchedSelectors, 357 handlerQueue = [], 358 delegateCount = handlers.delegateCount, 359 cur = event.target; 360 361 // Find delegate handlers 362 if ( delegateCount && 363 364 // Support: IE <=9 365 // Black-hole SVG <use> instance trees (trac-13180) 366 cur.nodeType && 367 368 // Support: Firefox <=42 369 // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) 370 // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click 371 // Support: IE 11 only 372 // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) 373 !( event.type === "click" && event.button >= 1 ) ) { 374 375 for ( ; cur !== this; cur = cur.parentNode || this ) { 376 377 // Don't check non-elements (trac-13208) 378 // Don't process clicks on disabled elements (trac-6911, trac-8165, trac-11382, trac-11764) 379 if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { 380 matchedHandlers = []; 381 matchedSelectors = {}; 382 for ( i = 0; i < delegateCount; i++ ) { 383 handleObj = handlers[ i ]; 384 385 // Don't conflict with Object.prototype properties (trac-13203) 386 sel = handleObj.selector + " "; 387 388 if ( matchedSelectors[ sel ] === undefined ) { 389 matchedSelectors[ sel ] = handleObj.needsContext ? 390 jQuery( sel, this ).index( cur ) > -1 : 391 jQuery.find( sel, this, null, [ cur ] ).length; 392 } 393 if ( matchedSelectors[ sel ] ) { 394 matchedHandlers.push( handleObj ); 395 } 396 } 397 if ( matchedHandlers.length ) { 398 handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); 399 } 400 } 401 } 402 } 403 404 // Add the remaining (directly-bound) handlers 405 cur = this; 406 if ( delegateCount < handlers.length ) { 407 handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); 408 } 409 410 return handlerQueue; 411 }, 412 413 addProp: function( name, hook ) { 414 Object.defineProperty( jQuery.Event.prototype, name, { 415 enumerable: true, 416 configurable: true, 417 418 get: isFunction( hook ) ? 419 function() { 420 if ( this.originalEvent ) { 421 return hook( this.originalEvent ); 422 } 423 } : 424 function() { 425 if ( this.originalEvent ) { 426 return this.originalEvent[ name ]; 427 } 428 }, 429 430 set: function( value ) { 431 Object.defineProperty( this, name, { 432 enumerable: true, 433 configurable: true, 434 writable: true, 435 value: value 436 } ); 437 } 438 } ); 439 }, 440 441 fix: function( originalEvent ) { 442 return originalEvent[ jQuery.expando ] ? 443 originalEvent : 444 new jQuery.Event( originalEvent ); 445 }, 446 447 special: { 448 load: { 449 450 // Prevent triggered image.load events from bubbling to window.load 451 noBubble: true 452 }, 453 click: { 454 455 // Utilize native event to ensure correct state for checkable inputs 456 setup: function( data ) { 457 458 // For mutual compressibility with _default, replace `this` access with a local var. 459 // `|| data` is dead code meant only to preserve the variable through minification. 460 var el = this || data; 461 462 // Claim the first handler 463 if ( rcheckableType.test( el.type ) && 464 el.click && nodeName( el, "input" ) ) { 465 466 // dataPriv.set( el, "click", ... ) 467 leverageNative( el, "click", true ); 468 } 469 470 // Return false to allow normal processing in the caller 471 return false; 472 }, 473 trigger: function( data ) { 474 475 // For mutual compressibility with _default, replace `this` access with a local var. 476 // `|| data` is dead code meant only to preserve the variable through minification. 477 var el = this || data; 478 479 // Force setup before triggering a click 480 if ( rcheckableType.test( el.type ) && 481 el.click && nodeName( el, "input" ) ) { 482 483 leverageNative( el, "click" ); 484 } 485 486 // Return non-false to allow normal event-path propagation 487 return true; 488 }, 489 490 // For cross-browser consistency, suppress native .click() on links 491 // Also prevent it if we're currently inside a leveraged native-event stack 492 _default: function( event ) { 493 var target = event.target; 494 return rcheckableType.test( target.type ) && 495 target.click && nodeName( target, "input" ) && 496 dataPriv.get( target, "click" ) || 497 nodeName( target, "a" ); 498 } 499 }, 500 501 beforeunload: { 502 postDispatch: function( event ) { 503 504 // Support: Firefox 20+ 505 // Firefox doesn't alert if the returnValue field is not set. 506 if ( event.result !== undefined && event.originalEvent ) { 507 event.originalEvent.returnValue = event.result; 508 } 509 } 510 } 511 } 512 }; 513 514 // Ensure the presence of an event listener that handles manually-triggered 515 // synthetic events by interrupting progress until reinvoked in response to 516 // *native* events that it fires directly, ensuring that state changes have 517 // already occurred before other listeners are invoked. 518 function leverageNative( el, type, isSetup ) { 519 520 // Missing `isSetup` indicates a trigger call, which must force setup through jQuery.event.add 521 if ( !isSetup ) { 522 if ( dataPriv.get( el, type ) === undefined ) { 523 jQuery.event.add( el, type, returnTrue ); 524 } 525 return; 526 } 527 528 // Register the controller as a special universal handler for all event namespaces 529 dataPriv.set( el, type, false ); 530 jQuery.event.add( el, type, { 531 namespace: false, 532 handler: function( event ) { 533 var result, 534 saved = dataPriv.get( this, type ); 535 536 if ( ( event.isTrigger & 1 ) && this[ type ] ) { 537 538 // Interrupt processing of the outer synthetic .trigger()ed event 539 if ( !saved ) { 540 541 // Store arguments for use when handling the inner native event 542 // There will always be at least one argument (an event object), so this array 543 // will not be confused with a leftover capture object. 544 saved = slice.call( arguments ); 545 dataPriv.set( this, type, saved ); 546 547 // Trigger the native event and capture its result 548 this[ type ](); 549 result = dataPriv.get( this, type ); 550 dataPriv.set( this, type, false ); 551 552 if ( saved !== result ) { 553 554 // Cancel the outer synthetic event 555 event.stopImmediatePropagation(); 556 event.preventDefault(); 557 558 return result; 559 } 560 561 // If this is an inner synthetic event for an event with a bubbling surrogate 562 // (focus or blur), assume that the surrogate already propagated from triggering 563 // the native event and prevent that from happening again here. 564 // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the 565 // bubbling surrogate propagates *after* the non-bubbling base), but that seems 566 // less bad than duplication. 567 } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { 568 event.stopPropagation(); 569 } 570 571 // If this is a native event triggered above, everything is now in order 572 // Fire an inner synthetic event with the original arguments 573 } else if ( saved ) { 574 575 // ...and capture the result 576 dataPriv.set( this, type, jQuery.event.trigger( 577 saved[ 0 ], 578 saved.slice( 1 ), 579 this 580 ) ); 581 582 // Abort handling of the native event by all jQuery handlers while allowing 583 // native handlers on the same element to run. On target, this is achieved 584 // by stopping immediate propagation just on the jQuery event. However, 585 // the native event is re-wrapped by a jQuery one on each level of the 586 // propagation so the only way to stop it for jQuery is to stop it for 587 // everyone via native `stopPropagation()`. This is not a problem for 588 // focus/blur which don't bubble, but it does also stop click on checkboxes 589 // and radios. We accept this limitation. 590 event.stopPropagation(); 591 event.isImmediatePropagationStopped = returnTrue; 592 } 593 } 594 } ); 595 } 596 597 jQuery.removeEvent = function( elem, type, handle ) { 598 599 // This "if" is needed for plain objects 600 if ( elem.removeEventListener ) { 601 elem.removeEventListener( type, handle ); 602 } 603 }; 604 605 jQuery.Event = function( src, props ) { 606 607 // Allow instantiation without the 'new' keyword 608 if ( !( this instanceof jQuery.Event ) ) { 609 return new jQuery.Event( src, props ); 610 } 611 612 // Event object 613 if ( src && src.type ) { 614 this.originalEvent = src; 615 this.type = src.type; 616 617 // Events bubbling up the document may have been marked as prevented 618 // by a handler lower down the tree; reflect the correct value. 619 this.isDefaultPrevented = src.defaultPrevented || 620 src.defaultPrevented === undefined && 621 622 // Support: Android <=2.3 only 623 src.returnValue === false ? 624 returnTrue : 625 returnFalse; 626 627 // Create target properties 628 // Support: Safari <=6 - 7 only 629 // Target should not be a text node (trac-504, trac-13143) 630 this.target = ( src.target && src.target.nodeType === 3 ) ? 631 src.target.parentNode : 632 src.target; 633 634 this.currentTarget = src.currentTarget; 635 this.relatedTarget = src.relatedTarget; 636 637 // Event type 638 } else { 639 this.type = src; 640 } 641 642 // Put explicitly provided properties onto the event object 643 if ( props ) { 644 jQuery.extend( this, props ); 645 } 646 647 // Create a timestamp if incoming event doesn't have one 648 this.timeStamp = src && src.timeStamp || Date.now(); 649 650 // Mark it as fixed 651 this[ jQuery.expando ] = true; 652 }; 653 654 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding 655 // https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html 656 jQuery.Event.prototype = { 657 constructor: jQuery.Event, 658 isDefaultPrevented: returnFalse, 659 isPropagationStopped: returnFalse, 660 isImmediatePropagationStopped: returnFalse, 661 isSimulated: false, 662 663 preventDefault: function() { 664 var e = this.originalEvent; 665 666 this.isDefaultPrevented = returnTrue; 667 668 if ( e && !this.isSimulated ) { 669 e.preventDefault(); 670 } 671 }, 672 stopPropagation: function() { 673 var e = this.originalEvent; 674 675 this.isPropagationStopped = returnTrue; 676 677 if ( e && !this.isSimulated ) { 678 e.stopPropagation(); 679 } 680 }, 681 stopImmediatePropagation: function() { 682 var e = this.originalEvent; 683 684 this.isImmediatePropagationStopped = returnTrue; 685 686 if ( e && !this.isSimulated ) { 687 e.stopImmediatePropagation(); 688 } 689 690 this.stopPropagation(); 691 } 692 }; 693 694 // Includes all common event props including KeyEvent and MouseEvent specific props 695 jQuery.each( { 696 altKey: true, 697 bubbles: true, 698 cancelable: true, 699 changedTouches: true, 700 ctrlKey: true, 701 detail: true, 702 eventPhase: true, 703 metaKey: true, 704 pageX: true, 705 pageY: true, 706 shiftKey: true, 707 view: true, 708 "char": true, 709 code: true, 710 charCode: true, 711 key: true, 712 keyCode: true, 713 button: true, 714 buttons: true, 715 clientX: true, 716 clientY: true, 717 offsetX: true, 718 offsetY: true, 719 pointerId: true, 720 pointerType: true, 721 screenX: true, 722 screenY: true, 723 targetTouches: true, 724 toElement: true, 725 touches: true, 726 which: true 727 }, jQuery.event.addProp ); 728 729 jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { 730 731 function focusMappedHandler( nativeEvent ) { 732 if ( document.documentMode ) { 733 734 // Support: IE 11+ 735 // Attach a single focusin/focusout handler on the document while someone wants 736 // focus/blur. This is because the former are synchronous in IE while the latter 737 // are async. In other browsers, all those handlers are invoked synchronously. 738 739 // `handle` from private data would already wrap the event, but we need 740 // to change the `type` here. 741 var handle = dataPriv.get( this, "handle" ), 742 event = jQuery.event.fix( nativeEvent ); 743 event.type = nativeEvent.type === "focusin" ? "focus" : "blur"; 744 event.isSimulated = true; 745 746 // First, handle focusin/focusout 747 handle( nativeEvent ); 748 749 // ...then, handle focus/blur 750 // 751 // focus/blur don't bubble while focusin/focusout do; simulate the former by only 752 // invoking the handler at the lower level. 753 if ( event.target === event.currentTarget ) { 754 755 // The setup part calls `leverageNative`, which, in turn, calls 756 // `jQuery.event.add`, so event handle will already have been set 757 // by this point. 758 handle( event ); 759 } 760 } else { 761 762 // For non-IE browsers, attach a single capturing handler on the document 763 // while someone wants focusin/focusout. 764 jQuery.event.simulate( delegateType, nativeEvent.target, 765 jQuery.event.fix( nativeEvent ) ); 766 } 767 } 768 769 jQuery.event.special[ type ] = { 770 771 // Utilize native event if possible so blur/focus sequence is correct 772 setup: function() { 773 774 var attaches; 775 776 // Claim the first handler 777 // dataPriv.set( this, "focus", ... ) 778 // dataPriv.set( this, "blur", ... ) 779 leverageNative( this, type, true ); 780 781 if ( document.documentMode ) { 782 783 // Support: IE 9 - 11+ 784 // We use the same native handler for focusin & focus (and focusout & blur) 785 // so we need to coordinate setup & teardown parts between those events. 786 // Use `delegateType` as the key as `type` is already used by `leverageNative`. 787 attaches = dataPriv.get( this, delegateType ); 788 if ( !attaches ) { 789 this.addEventListener( delegateType, focusMappedHandler ); 790 } 791 dataPriv.set( this, delegateType, ( attaches || 0 ) + 1 ); 792 } else { 793 794 // Return false to allow normal processing in the caller 795 return false; 796 } 797 }, 798 trigger: function() { 799 800 // Force setup before trigger 801 leverageNative( this, type ); 802 803 // Return non-false to allow normal event-path propagation 804 return true; 805 }, 806 807 teardown: function() { 808 var attaches; 809 810 if ( document.documentMode ) { 811 attaches = dataPriv.get( this, delegateType ) - 1; 812 if ( !attaches ) { 813 this.removeEventListener( delegateType, focusMappedHandler ); 814 dataPriv.remove( this, delegateType ); 815 } else { 816 dataPriv.set( this, delegateType, attaches ); 817 } 818 } else { 819 820 // Return false to indicate standard teardown should be applied 821 return false; 822 } 823 }, 824 825 // Suppress native focus or blur if we're currently inside 826 // a leveraged native-event stack 827 _default: function( event ) { 828 return dataPriv.get( event.target, type ); 829 }, 830 831 delegateType: delegateType 832 }; 833 834 // Support: Firefox <=44 835 // Firefox doesn't have focus(in | out) events 836 // Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 837 // 838 // Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 839 // focus(in | out) events fire after focus & blur events, 840 // which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order 841 // Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 842 // 843 // Support: IE 9 - 11+ 844 // To preserve relative focusin/focus & focusout/blur event order guaranteed on the 3.x branch, 845 // attach a single handler for both events in IE. 846 jQuery.event.special[ delegateType ] = { 847 setup: function() { 848 849 // Handle: regular nodes (via `this.ownerDocument`), window 850 // (via `this.document`) & document (via `this`). 851 var doc = this.ownerDocument || this.document || this, 852 dataHolder = document.documentMode ? this : doc, 853 attaches = dataPriv.get( dataHolder, delegateType ); 854 855 // Support: IE 9 - 11+ 856 // We use the same native handler for focusin & focus (and focusout & blur) 857 // so we need to coordinate setup & teardown parts between those events. 858 // Use `delegateType` as the key as `type` is already used by `leverageNative`. 859 if ( !attaches ) { 860 if ( document.documentMode ) { 861 this.addEventListener( delegateType, focusMappedHandler ); 862 } else { 863 doc.addEventListener( type, focusMappedHandler, true ); 864 } 865 } 866 dataPriv.set( dataHolder, delegateType, ( attaches || 0 ) + 1 ); 867 }, 868 teardown: function() { 869 var doc = this.ownerDocument || this.document || this, 870 dataHolder = document.documentMode ? this : doc, 871 attaches = dataPriv.get( dataHolder, delegateType ) - 1; 872 873 if ( !attaches ) { 874 if ( document.documentMode ) { 875 this.removeEventListener( delegateType, focusMappedHandler ); 876 } else { 877 doc.removeEventListener( type, focusMappedHandler, true ); 878 } 879 dataPriv.remove( dataHolder, delegateType ); 880 } else { 881 dataPriv.set( dataHolder, delegateType, attaches ); 882 } 883 } 884 }; 885 } ); 886 887 // Create mouseenter/leave events using mouseover/out and event-time checks 888 // so that event delegation works in jQuery. 889 // Do the same for pointerenter/pointerleave and pointerover/pointerout 890 // 891 // Support: Safari 7 only 892 // Safari sends mouseenter too often; see: 893 // https://bugs.chromium.org/p/chromium/issues/detail?id=470258 894 // for the description of the bug (it existed in older Chrome versions as well). 895 jQuery.each( { 896 mouseenter: "mouseover", 897 mouseleave: "mouseout", 898 pointerenter: "pointerover", 899 pointerleave: "pointerout" 900 }, function( orig, fix ) { 901 jQuery.event.special[ orig ] = { 902 delegateType: fix, 903 bindType: fix, 904 905 handle: function( event ) { 906 var ret, 907 target = this, 908 related = event.relatedTarget, 909 handleObj = event.handleObj; 910 911 // For mouseenter/leave call the handler if related is outside the target. 912 // NB: No relatedTarget if the mouse left/entered the browser window 913 if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { 914 event.type = handleObj.origType; 915 ret = handleObj.handler.apply( this, arguments ); 916 event.type = fix; 917 } 918 return ret; 919 } 920 }; 921 } ); 922 923 jQuery.fn.extend( { 924 925 on: function( types, selector, data, fn ) { 926 return on( this, types, selector, data, fn ); 927 }, 928 one: function( types, selector, data, fn ) { 929 return on( this, types, selector, data, fn, 1 ); 930 }, 931 off: function( types, selector, fn ) { 932 var handleObj, type; 933 if ( types && types.preventDefault && types.handleObj ) { 934 935 // ( event ) dispatched jQuery.Event 936 handleObj = types.handleObj; 937 jQuery( types.delegateTarget ).off( 938 handleObj.namespace ? 939 handleObj.origType + "." + handleObj.namespace : 940 handleObj.origType, 941 handleObj.selector, 942 handleObj.handler 943 ); 944 return this; 945 } 946 if ( typeof types === "object" ) { 947 948 // ( types-object [, selector] ) 949 for ( type in types ) { 950 this.off( type, selector, types[ type ] ); 951 } 952 return this; 953 } 954 if ( selector === false || typeof selector === "function" ) { 955 956 // ( types [, fn] ) 957 fn = selector; 958 selector = undefined; 959 } 960 if ( fn === false ) { 961 fn = returnFalse; 962 } 963 return this.each( function() { 964 jQuery.event.remove( this, types, fn, selector ); 965 } ); 966 } 967 } ); 968 969 return jQuery; 970 } );