trigger.js 5.3 KB

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