event.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. var rkeyEvent = /^key/,
  2. rmouseEvent = /^(?:mouse|contextmenu)|click/,
  3. rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
  4. rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
  5. function returnTrue() {
  6. return true;
  7. }
  8. function returnFalse() {
  9. return false;
  10. }
  11. function safeActiveElement() {
  12. try {
  13. return document.activeElement;
  14. } catch ( err ) { }
  15. }
  16. /*
  17. * Helper functions for managing events -- not part of the public interface.
  18. * Props to Dean Edwards' addEvent library for many of the ideas.
  19. */
  20. jQuery.event = {
  21. global: {},
  22. add: function( elem, types, handler, data, selector ) {
  23. var handleObjIn, eventHandle, tmp,
  24. events, t, handleObj,
  25. special, handlers, type, namespaces, origType,
  26. elemData = data_priv.get( elem );
  27. // Don't attach events to noData or text/comment nodes (but allow plain objects)
  28. if ( !elemData ) {
  29. return;
  30. }
  31. // Caller can pass in an object of custom data in lieu of the handler
  32. if ( handler.handler ) {
  33. handleObjIn = handler;
  34. handler = handleObjIn.handler;
  35. selector = handleObjIn.selector;
  36. }
  37. // Make sure that the handler has a unique ID, used to find/remove it later
  38. if ( !handler.guid ) {
  39. handler.guid = jQuery.guid++;
  40. }
  41. // Init the element's event structure and main handler, if this is the first
  42. if ( !(events = elemData.events) ) {
  43. events = elemData.events = {};
  44. }
  45. if ( !(eventHandle = elemData.handle) ) {
  46. eventHandle = elemData.handle = function( e ) {
  47. // Discard the second event of a jQuery.event.trigger() and
  48. // when an event is called after a page has unloaded
  49. return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
  50. jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
  51. undefined;
  52. };
  53. // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
  54. eventHandle.elem = elem;
  55. }
  56. // Handle multiple events separated by a space
  57. types = ( types || "" ).match( core_rnotwhite ) || [""];
  58. t = types.length;
  59. while ( t-- ) {
  60. tmp = rtypenamespace.exec( types[t] ) || [];
  61. type = origType = tmp[1];
  62. namespaces = ( tmp[2] || "" ).split( "." ).sort();
  63. // There *must* be a type, no attaching namespace-only handlers
  64. if ( !type ) {
  65. continue;
  66. }
  67. // If event changes its type, use the special event handlers for the changed type
  68. special = jQuery.event.special[ type ] || {};
  69. // If selector defined, determine special event api type, otherwise given type
  70. type = ( selector ? special.delegateType : special.bindType ) || type;
  71. // Update special based on newly reset type
  72. special = jQuery.event.special[ type ] || {};
  73. // handleObj is passed to all event handlers
  74. handleObj = jQuery.extend({
  75. type: type,
  76. origType: origType,
  77. data: data,
  78. handler: handler,
  79. guid: handler.guid,
  80. selector: selector,
  81. needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
  82. namespace: namespaces.join(".")
  83. }, handleObjIn );
  84. // Init the event handler queue if we're the first
  85. if ( !(handlers = events[ type ]) ) {
  86. handlers = events[ type ] = [];
  87. handlers.delegateCount = 0;
  88. // Only use addEventListener if the special events handler returns false
  89. if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
  90. if ( elem.addEventListener ) {
  91. elem.addEventListener( type, eventHandle, false );
  92. }
  93. }
  94. }
  95. if ( special.add ) {
  96. special.add.call( elem, handleObj );
  97. if ( !handleObj.handler.guid ) {
  98. handleObj.handler.guid = handler.guid;
  99. }
  100. }
  101. // Add to the element's handler list, delegates in front
  102. if ( selector ) {
  103. handlers.splice( handlers.delegateCount++, 0, handleObj );
  104. } else {
  105. handlers.push( handleObj );
  106. }
  107. // Keep track of which events have ever been used, for event optimization
  108. jQuery.event.global[ type ] = true;
  109. }
  110. // Nullify elem to prevent memory leaks in IE
  111. elem = null;
  112. },
  113. // Detach an event or set of events from an element
  114. remove: function( elem, types, handler, selector, mappedTypes ) {
  115. var j, origCount, tmp,
  116. events, t, handleObj,
  117. special, handlers, type, namespaces, origType,
  118. elemData = data_priv.hasData( elem ) && data_priv.get( elem );
  119. if ( !elemData || !(events = elemData.events) ) {
  120. return;
  121. }
  122. // Once for each type.namespace in types; type may be omitted
  123. types = ( types || "" ).match( core_rnotwhite ) || [""];
  124. t = types.length;
  125. while ( t-- ) {
  126. tmp = rtypenamespace.exec( types[t] ) || [];
  127. type = origType = tmp[1];
  128. namespaces = ( tmp[2] || "" ).split( "." ).sort();
  129. // Unbind all events (on this namespace, if provided) for the element
  130. if ( !type ) {
  131. for ( type in events ) {
  132. jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
  133. }
  134. continue;
  135. }
  136. special = jQuery.event.special[ type ] || {};
  137. type = ( selector ? special.delegateType : special.bindType ) || type;
  138. handlers = events[ type ] || [];
  139. tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
  140. // Remove matching events
  141. origCount = j = handlers.length;
  142. while ( j-- ) {
  143. handleObj = handlers[ j ];
  144. if ( ( mappedTypes || origType === handleObj.origType ) &&
  145. ( !handler || handler.guid === handleObj.guid ) &&
  146. ( !tmp || tmp.test( handleObj.namespace ) ) &&
  147. ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
  148. handlers.splice( j, 1 );
  149. if ( handleObj.selector ) {
  150. handlers.delegateCount--;
  151. }
  152. if ( special.remove ) {
  153. special.remove.call( elem, handleObj );
  154. }
  155. }
  156. }
  157. // Remove generic event handler if we removed something and no more handlers exist
  158. // (avoids potential for endless recursion during removal of special event handlers)
  159. if ( origCount && !handlers.length ) {
  160. if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
  161. jQuery.removeEvent( elem, type, elemData.handle );
  162. }
  163. delete events[ type ];
  164. }
  165. }
  166. // Remove the expando if it's no longer used
  167. if ( jQuery.isEmptyObject( events ) ) {
  168. delete elemData.handle;
  169. data_priv.remove( elem, "events" );
  170. }
  171. },
  172. trigger: function( event, data, elem, onlyHandlers ) {
  173. var i, cur, tmp, bubbleType, ontype, handle, special,
  174. eventPath = [ elem || document ],
  175. type = core_hasOwn.call( event, "type" ) ? event.type : event,
  176. namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
  177. cur = tmp = elem = elem || document;
  178. // Don't do events on text and comment nodes
  179. if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
  180. return;
  181. }
  182. // focus/blur morphs to focusin/out; ensure we're not firing them right now
  183. if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
  184. return;
  185. }
  186. if ( type.indexOf(".") >= 0 ) {
  187. // Namespaced trigger; create a regexp to match event type in handle()
  188. namespaces = type.split(".");
  189. type = namespaces.shift();
  190. namespaces.sort();
  191. }
  192. ontype = type.indexOf(":") < 0 && "on" + type;
  193. // Caller can pass in a jQuery.Event object, Object, or just an event type string
  194. event = event[ jQuery.expando ] ?
  195. event :
  196. new jQuery.Event( type, typeof event === "object" && event );
  197. // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
  198. event.isTrigger = onlyHandlers ? 2 : 3;
  199. event.namespace = namespaces.join(".");
  200. event.namespace_re = event.namespace ?
  201. new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
  202. null;
  203. // Clean up the event in case it is being reused
  204. event.result = undefined;
  205. if ( !event.target ) {
  206. event.target = elem;
  207. }
  208. // Clone any incoming data and prepend the event, creating the handler arg list
  209. data = data == null ?
  210. [ event ] :
  211. jQuery.makeArray( data, [ event ] );
  212. // Allow special events to draw outside the lines
  213. special = jQuery.event.special[ type ] || {};
  214. if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
  215. return;
  216. }
  217. // Determine event propagation path in advance, per W3C events spec (#9951)
  218. // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
  219. if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
  220. bubbleType = special.delegateType || type;
  221. if ( !rfocusMorph.test( bubbleType + type ) ) {
  222. cur = cur.parentNode;
  223. }
  224. for ( ; cur; cur = cur.parentNode ) {
  225. eventPath.push( cur );
  226. tmp = cur;
  227. }
  228. // Only add window if we got to document (e.g., not plain obj or detached DOM)
  229. if ( tmp === (elem.ownerDocument || document) ) {
  230. eventPath.push( tmp.defaultView || tmp.parentWindow || window );
  231. }
  232. }
  233. // Fire handlers on the event path
  234. i = 0;
  235. while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
  236. event.type = i > 1 ?
  237. bubbleType :
  238. special.bindType || type;
  239. // jQuery handler
  240. handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" );
  241. if ( handle ) {
  242. handle.apply( cur, data );
  243. }
  244. // Native handler
  245. handle = ontype && cur[ ontype ];
  246. if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
  247. event.preventDefault();
  248. }
  249. }
  250. event.type = type;
  251. // If nobody prevented the default action, do it now
  252. if ( !onlyHandlers && !event.isDefaultPrevented() ) {
  253. if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
  254. jQuery.acceptData( elem ) ) {
  255. // Call a native DOM method on the target with the same name name as the event.
  256. // Don't do default actions on window, that's where global variables be (#6170)
  257. if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
  258. // Don't re-trigger an onFOO event when we call its FOO() method
  259. tmp = elem[ ontype ];
  260. if ( tmp ) {
  261. elem[ ontype ] = null;
  262. }
  263. // Prevent re-triggering of the same event, since we already bubbled it above
  264. jQuery.event.triggered = type;
  265. elem[ type ]();
  266. jQuery.event.triggered = undefined;
  267. if ( tmp ) {
  268. elem[ ontype ] = tmp;
  269. }
  270. }
  271. }
  272. }
  273. return event.result;
  274. },
  275. dispatch: function( event ) {
  276. // Make a writable jQuery.Event from the native event object
  277. event = jQuery.event.fix( event );
  278. var i, j, ret, matched, handleObj,
  279. handlerQueue = [],
  280. args = core_slice.call( arguments ),
  281. handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [],
  282. special = jQuery.event.special[ event.type ] || {};
  283. // Use the fix-ed jQuery.Event rather than the (read-only) native event
  284. args[0] = event;
  285. event.delegateTarget = this;
  286. // Call the preDispatch hook for the mapped type, and let it bail if desired
  287. if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
  288. return;
  289. }
  290. // Determine handlers
  291. handlerQueue = jQuery.event.handlers.call( this, event, handlers );
  292. // Run delegates first; they may want to stop propagation beneath us
  293. i = 0;
  294. while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
  295. event.currentTarget = matched.elem;
  296. j = 0;
  297. while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
  298. // Triggered event must either 1) have no namespace, or
  299. // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
  300. if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
  301. event.handleObj = handleObj;
  302. event.data = handleObj.data;
  303. ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
  304. .apply( matched.elem, args );
  305. if ( ret !== undefined ) {
  306. if ( (event.result = ret) === false ) {
  307. event.preventDefault();
  308. event.stopPropagation();
  309. }
  310. }
  311. }
  312. }
  313. }
  314. // Call the postDispatch hook for the mapped type
  315. if ( special.postDispatch ) {
  316. special.postDispatch.call( this, event );
  317. }
  318. return event.result;
  319. },
  320. handlers: function( event, handlers ) {
  321. var i, matches, sel, handleObj,
  322. handlerQueue = [],
  323. delegateCount = handlers.delegateCount,
  324. cur = event.target;
  325. // Find delegate handlers
  326. // Black-hole SVG <use> instance trees (#13180)
  327. // Avoid non-left-click bubbling in Firefox (#3861)
  328. if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
  329. for ( ; cur !== this; cur = cur.parentNode || this ) {
  330. // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
  331. if ( cur.disabled !== true || event.type !== "click" ) {
  332. matches = [];
  333. for ( i = 0; i < delegateCount; i++ ) {
  334. handleObj = handlers[ i ];
  335. // Don't conflict with Object.prototype properties (#13203)
  336. sel = handleObj.selector + " ";
  337. if ( matches[ sel ] === undefined ) {
  338. matches[ sel ] = handleObj.needsContext ?
  339. jQuery( sel, this ).index( cur ) >= 0 :
  340. jQuery.find( sel, this, null, [ cur ] ).length;
  341. }
  342. if ( matches[ sel ] ) {
  343. matches.push( handleObj );
  344. }
  345. }
  346. if ( matches.length ) {
  347. handlerQueue.push({ elem: cur, handlers: matches });
  348. }
  349. }
  350. }
  351. }
  352. // Add the remaining (directly-bound) handlers
  353. if ( delegateCount < handlers.length ) {
  354. handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
  355. }
  356. return handlerQueue;
  357. },
  358. // Includes some event props shared by KeyEvent and MouseEvent
  359. props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
  360. fixHooks: {},
  361. keyHooks: {
  362. props: "char charCode key keyCode".split(" "),
  363. filter: function( event, original ) {
  364. // Add which for key events
  365. if ( event.which == null ) {
  366. event.which = original.charCode != null ? original.charCode : original.keyCode;
  367. }
  368. return event;
  369. }
  370. },
  371. mouseHooks: {
  372. props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
  373. filter: function( event, original ) {
  374. var eventDoc, doc, body,
  375. button = original.button;
  376. // Calculate pageX/Y if missing and clientX/Y available
  377. if ( event.pageX == null && original.clientX != null ) {
  378. eventDoc = event.target.ownerDocument || document;
  379. doc = eventDoc.documentElement;
  380. body = eventDoc.body;
  381. event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
  382. event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
  383. }
  384. // Add which for click: 1 === left; 2 === middle; 3 === right
  385. // Note: button is not normalized, so don't use it
  386. if ( !event.which && button !== undefined ) {
  387. event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
  388. }
  389. return event;
  390. }
  391. },
  392. fix: function( event ) {
  393. if ( event[ jQuery.expando ] ) {
  394. return event;
  395. }
  396. // Create a writable copy of the event object and normalize some properties
  397. var i, prop, copy,
  398. type = event.type,
  399. originalEvent = event,
  400. fixHook = this.fixHooks[ type ];
  401. if ( !fixHook ) {
  402. this.fixHooks[ type ] = fixHook =
  403. rmouseEvent.test( type ) ? this.mouseHooks :
  404. rkeyEvent.test( type ) ? this.keyHooks :
  405. {};
  406. }
  407. copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
  408. event = new jQuery.Event( originalEvent );
  409. i = copy.length;
  410. while ( i-- ) {
  411. prop = copy[ i ];
  412. event[ prop ] = originalEvent[ prop ];
  413. }
  414. // Support: Cordova 2.5 (WebKit) (#13255)
  415. // All events should have a target; Cordova deviceready doesn't
  416. if ( !event.target ) {
  417. event.target = document;
  418. }
  419. // Support: Safari 6.0+, Chrome < 28
  420. // Target should not be a text node (#504, #13143)
  421. if ( event.target.nodeType === 3 ) {
  422. event.target = event.target.parentNode;
  423. }
  424. return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
  425. },
  426. special: {
  427. load: {
  428. // Prevent triggered image.load events from bubbling to window.load
  429. noBubble: true
  430. },
  431. focus: {
  432. // Fire native event if possible so blur/focus sequence is correct
  433. trigger: function() {
  434. if ( this !== safeActiveElement() && this.focus ) {
  435. this.focus();
  436. return false;
  437. }
  438. },
  439. delegateType: "focusin"
  440. },
  441. blur: {
  442. trigger: function() {
  443. if ( this === safeActiveElement() && this.blur ) {
  444. this.blur();
  445. return false;
  446. }
  447. },
  448. delegateType: "focusout"
  449. },
  450. click: {
  451. // For checkbox, fire native event so checked state will be right
  452. trigger: function() {
  453. if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
  454. this.click();
  455. return false;
  456. }
  457. },
  458. // For cross-browser consistency, don't fire native .click() on links
  459. _default: function( event ) {
  460. return jQuery.nodeName( event.target, "a" );
  461. }
  462. },
  463. beforeunload: {
  464. postDispatch: function( event ) {
  465. // Support: Firefox 20+
  466. // Firefox doesn't alert if the returnValue field is not set.
  467. if ( event.result !== undefined ) {
  468. event.originalEvent.returnValue = event.result;
  469. }
  470. }
  471. }
  472. },
  473. simulate: function( type, elem, event, bubble ) {
  474. // Piggyback on a donor event to simulate a different one.
  475. // Fake originalEvent to avoid donor's stopPropagation, but if the
  476. // simulated event prevents default then we do the same on the donor.
  477. var e = jQuery.extend(
  478. new jQuery.Event(),
  479. event,
  480. {
  481. type: type,
  482. isSimulated: true,
  483. originalEvent: {}
  484. }
  485. );
  486. if ( bubble ) {
  487. jQuery.event.trigger( e, null, elem );
  488. } else {
  489. jQuery.event.dispatch.call( elem, e );
  490. }
  491. if ( e.isDefaultPrevented() ) {
  492. event.preventDefault();
  493. }
  494. }
  495. };
  496. jQuery.removeEvent = function( elem, type, handle ) {
  497. if ( elem.removeEventListener ) {
  498. elem.removeEventListener( type, handle, false );
  499. }
  500. };
  501. jQuery.Event = function( src, props ) {
  502. // Allow instantiation without the 'new' keyword
  503. if ( !(this instanceof jQuery.Event) ) {
  504. return new jQuery.Event( src, props );
  505. }
  506. // Event object
  507. if ( src && src.type ) {
  508. this.originalEvent = src;
  509. this.type = src.type;
  510. // Events bubbling up the document may have been marked as prevented
  511. // by a handler lower down the tree; reflect the correct value.
  512. this.isDefaultPrevented = ( src.defaultPrevented ||
  513. src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
  514. // Event type
  515. } else {
  516. this.type = src;
  517. }
  518. // Put explicitly provided properties onto the event object
  519. if ( props ) {
  520. jQuery.extend( this, props );
  521. }
  522. // Create a timestamp if incoming event doesn't have one
  523. this.timeStamp = src && src.timeStamp || jQuery.now();
  524. // Mark it as fixed
  525. this[ jQuery.expando ] = true;
  526. };
  527. // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
  528. // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
  529. jQuery.Event.prototype = {
  530. isDefaultPrevented: returnFalse,
  531. isPropagationStopped: returnFalse,
  532. isImmediatePropagationStopped: returnFalse,
  533. preventDefault: function() {
  534. var e = this.originalEvent;
  535. this.isDefaultPrevented = returnTrue;
  536. if ( e && e.preventDefault ) {
  537. e.preventDefault();
  538. }
  539. },
  540. stopPropagation: function() {
  541. var e = this.originalEvent;
  542. this.isPropagationStopped = returnTrue;
  543. if ( e && e.stopPropagation ) {
  544. e.stopPropagation();
  545. }
  546. },
  547. stopImmediatePropagation: function() {
  548. this.isImmediatePropagationStopped = returnTrue;
  549. this.stopPropagation();
  550. }
  551. };
  552. // Create mouseenter/leave events using mouseover/out and event-time checks
  553. // Support: Chrome 15+
  554. jQuery.each({
  555. mouseenter: "mouseover",
  556. mouseleave: "mouseout"
  557. }, function( orig, fix ) {
  558. jQuery.event.special[ orig ] = {
  559. delegateType: fix,
  560. bindType: fix,
  561. handle: function( event ) {
  562. var ret,
  563. target = this,
  564. related = event.relatedTarget,
  565. handleObj = event.handleObj;
  566. // For mousenter/leave call the handler if related is outside the target.
  567. // NB: No relatedTarget if the mouse left/entered the browser window
  568. if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
  569. event.type = handleObj.origType;
  570. ret = handleObj.handler.apply( this, arguments );
  571. event.type = fix;
  572. }
  573. return ret;
  574. }
  575. };
  576. });
  577. // Create "bubbling" focus and blur events
  578. // Support: Firefox, Chrome, Safari
  579. if ( !jQuery.support.focusinBubbles ) {
  580. jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
  581. // Attach a single capturing handler while someone wants focusin/focusout
  582. var attaches = 0,
  583. handler = function( event ) {
  584. jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
  585. };
  586. jQuery.event.special[ fix ] = {
  587. setup: function() {
  588. if ( attaches++ === 0 ) {
  589. document.addEventListener( orig, handler, true );
  590. }
  591. },
  592. teardown: function() {
  593. if ( --attaches === 0 ) {
  594. document.removeEventListener( orig, handler, true );
  595. }
  596. }
  597. };
  598. });
  599. }
  600. jQuery.fn.extend({
  601. on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
  602. var origFn, type;
  603. // Types can be a map of types/handlers
  604. if ( typeof types === "object" ) {
  605. // ( types-Object, selector, data )
  606. if ( typeof selector !== "string" ) {
  607. // ( types-Object, data )
  608. data = data || selector;
  609. selector = undefined;
  610. }
  611. for ( type in types ) {
  612. this.on( type, selector, data, types[ type ], one );
  613. }
  614. return this;
  615. }
  616. if ( data == null && fn == null ) {
  617. // ( types, fn )
  618. fn = selector;
  619. data = selector = undefined;
  620. } else if ( fn == null ) {
  621. if ( typeof selector === "string" ) {
  622. // ( types, selector, fn )
  623. fn = data;
  624. data = undefined;
  625. } else {
  626. // ( types, data, fn )
  627. fn = data;
  628. data = selector;
  629. selector = undefined;
  630. }
  631. }
  632. if ( fn === false ) {
  633. fn = returnFalse;
  634. } else if ( !fn ) {
  635. return this;
  636. }
  637. if ( one === 1 ) {
  638. origFn = fn;
  639. fn = function( event ) {
  640. // Can use an empty set, since event contains the info
  641. jQuery().off( event );
  642. return origFn.apply( this, arguments );
  643. };
  644. // Use same guid so caller can remove using origFn
  645. fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
  646. }
  647. return this.each( function() {
  648. jQuery.event.add( this, types, fn, data, selector );
  649. });
  650. },
  651. one: function( types, selector, data, fn ) {
  652. return this.on( types, selector, data, fn, 1 );
  653. },
  654. off: function( types, selector, fn ) {
  655. var handleObj, type;
  656. if ( types && types.preventDefault && types.handleObj ) {
  657. // ( event ) dispatched jQuery.Event
  658. handleObj = types.handleObj;
  659. jQuery( types.delegateTarget ).off(
  660. handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
  661. handleObj.selector,
  662. handleObj.handler
  663. );
  664. return this;
  665. }
  666. if ( typeof types === "object" ) {
  667. // ( types-object [, selector] )
  668. for ( type in types ) {
  669. this.off( type, selector, types[ type ] );
  670. }
  671. return this;
  672. }
  673. if ( selector === false || typeof selector === "function" ) {
  674. // ( types [, fn] )
  675. fn = selector;
  676. selector = undefined;
  677. }
  678. if ( fn === false ) {
  679. fn = returnFalse;
  680. }
  681. return this.each(function() {
  682. jQuery.event.remove( this, types, fn, selector );
  683. });
  684. },
  685. trigger: function( type, data ) {
  686. return this.each(function() {
  687. jQuery.event.trigger( type, data, this );
  688. });
  689. },
  690. triggerHandler: function( type, data ) {
  691. var elem = this[0];
  692. if ( elem ) {
  693. return jQuery.event.trigger( type, data, elem, true );
  694. }
  695. }
  696. });