trigger.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. define( [
  2. "../core",
  3. "../var/document",
  4. "../data/var/dataPriv",
  5. "../data/var/acceptData",
  6. "../var/hasOwn",
  7. "../event"
  8. ], function( jQuery, document, dataPriv, acceptData, hasOwn ) {
  9. "use strict";
  10. var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;
  11. jQuery.extend( jQuery.event, {
  12. trigger: function( event, data, elem, onlyHandlers ) {
  13. var i, cur, tmp, bubbleType, ontype, handle, special,
  14. eventPath = [ elem || document ],
  15. type = hasOwn.call( event, "type" ) ? event.type : event,
  16. namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
  17. cur = tmp = elem = elem || document;
  18. // Don't do events on text and comment nodes
  19. if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
  20. return;
  21. }
  22. // focus/blur morphs to focusin/out; ensure we're not firing them right now
  23. if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
  24. return;
  25. }
  26. if ( type.indexOf( "." ) > -1 ) {
  27. // Namespaced trigger; create a regexp to match event type in handle()
  28. namespaces = type.split( "." );
  29. type = namespaces.shift();
  30. namespaces.sort();
  31. }
  32. ontype = type.indexOf( ":" ) < 0 && "on" + type;
  33. // Caller can pass in a jQuery.Event object, Object, or just an event type string
  34. event = event[ jQuery.expando ] ?
  35. event :
  36. new jQuery.Event( type, typeof event === "object" && event );
  37. // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
  38. event.isTrigger = onlyHandlers ? 2 : 3;
  39. event.namespace = namespaces.join( "." );
  40. event.rnamespace = event.namespace ?
  41. new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
  42. null;
  43. // Clean up the event in case it is being reused
  44. event.result = undefined;
  45. if ( !event.target ) {
  46. event.target = elem;
  47. }
  48. // Clone any incoming data and prepend the event, creating the handler arg list
  49. data = data == null ?
  50. [ event ] :
  51. jQuery.makeArray( data, [ event ] );
  52. // Allow special events to draw outside the lines
  53. special = jQuery.event.special[ type ] || {};
  54. if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
  55. return;
  56. }
  57. // Determine event propagation path in advance, per W3C events spec (#9951)
  58. // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
  59. if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
  60. bubbleType = special.delegateType || type;
  61. if ( !rfocusMorph.test( bubbleType + type ) ) {
  62. cur = cur.parentNode;
  63. }
  64. for ( ; cur; cur = cur.parentNode ) {
  65. eventPath.push( cur );
  66. tmp = cur;
  67. }
  68. // Only add window if we got to document (e.g., not plain obj or detached DOM)
  69. if ( tmp === ( elem.ownerDocument || document ) ) {
  70. eventPath.push( tmp.defaultView || tmp.parentWindow || window );
  71. }
  72. }
  73. // Fire handlers on the event path
  74. i = 0;
  75. while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
  76. event.type = i > 1 ?
  77. bubbleType :
  78. special.bindType || type;
  79. // jQuery handler
  80. handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
  81. dataPriv.get( cur, "handle" );
  82. if ( handle ) {
  83. handle.apply( cur, data );
  84. }
  85. // Native handler
  86. handle = ontype && cur[ ontype ];
  87. if ( handle && handle.apply && acceptData( cur ) ) {
  88. event.result = handle.apply( cur, data );
  89. if ( event.result === false ) {
  90. event.preventDefault();
  91. }
  92. }
  93. }
  94. event.type = type;
  95. // If nobody prevented the default action, do it now
  96. if ( !onlyHandlers && !event.isDefaultPrevented() ) {
  97. if ( ( !special._default ||
  98. special._default.apply( eventPath.pop(), data ) === false ) &&
  99. acceptData( elem ) ) {
  100. // Call a native DOM method on the target with the same name as the event.
  101. // Don't do default actions on window, that's where global variables be (#6170)
  102. if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
  103. // Don't re-trigger an onFOO event when we call its FOO() method
  104. tmp = elem[ ontype ];
  105. if ( tmp ) {
  106. elem[ ontype ] = null;
  107. }
  108. // Prevent re-triggering of the same event, since we already bubbled it above
  109. jQuery.event.triggered = type;
  110. elem[ type ]();
  111. jQuery.event.triggered = undefined;
  112. if ( tmp ) {
  113. elem[ ontype ] = tmp;
  114. }
  115. }
  116. }
  117. }
  118. return event.result;
  119. },
  120. // Piggyback on a donor event to simulate a different one
  121. // Used only for `focus(in | out)` events
  122. simulate: function( type, elem, event ) {
  123. var e = jQuery.extend(
  124. new jQuery.Event(),
  125. event,
  126. {
  127. type: type,
  128. isSimulated: true
  129. }
  130. );
  131. jQuery.event.trigger( e, null, elem );
  132. }
  133. } );
  134. jQuery.fn.extend( {
  135. trigger: function( type, data ) {
  136. return this.each( function() {
  137. jQuery.event.trigger( type, data, this );
  138. } );
  139. },
  140. triggerHandler: function( type, data ) {
  141. var elem = this[ 0 ];
  142. if ( elem ) {
  143. return jQuery.event.trigger( type, data, elem, true );
  144. }
  145. }
  146. } );
  147. return jQuery;
  148. } );