event.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991
  1. var rformElems = /^(?:input|select|textarea)$/i,
  2. rkeyEvent = /^key/,
  3. rmouseEvent = /^(?:mouse|contextmenu)|click/,
  4. rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
  5. rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
  6. function returnTrue() {
  7. return true;
  8. }
  9. function returnFalse() {
  10. return false;
  11. }
  12. /*
  13. * Helper functions for managing events -- not part of the public interface.
  14. * Props to Dean Edwards' addEvent library for many of the ideas.
  15. */
  16. jQuery.event = {
  17. global: {},
  18. add: function( elem, types, handler, data, selector ) {
  19. var tmp, events, t, handleObjIn,
  20. special, eventHandle, handleObj,
  21. handlers, type, namespaces, origType,
  22. elemData = jQuery._data( elem );
  23. // Don't attach events to noData or text/comment nodes (but allow plain objects)
  24. if ( !elemData ) {
  25. return;
  26. }
  27. // Caller can pass in an object of custom data in lieu of the handler
  28. if ( handler.handler ) {
  29. handleObjIn = handler;
  30. handler = handleObjIn.handler;
  31. selector = handleObjIn.selector;
  32. }
  33. // Make sure that the handler has a unique ID, used to find/remove it later
  34. if ( !handler.guid ) {
  35. handler.guid = jQuery.guid++;
  36. }
  37. // Init the element's event structure and main handler, if this is the first
  38. if ( !(events = elemData.events) ) {
  39. events = elemData.events = {};
  40. }
  41. if ( !(eventHandle = elemData.handle) ) {
  42. eventHandle = elemData.handle = function( e ) {
  43. // Discard the second event of a jQuery.event.trigger() and
  44. // when an event is called after a page has unloaded
  45. return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
  46. jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
  47. undefined;
  48. };
  49. // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
  50. eventHandle.elem = elem;
  51. }
  52. // Handle multiple events separated by a space
  53. // jQuery(...).bind("mouseover mouseout", fn);
  54. types = ( types || "" ).match( core_rnotwhite ) || [""];
  55. t = types.length;
  56. while ( t-- ) {
  57. tmp = rtypenamespace.exec( types[t] ) || [];
  58. type = origType = tmp[1];
  59. namespaces = ( tmp[2] || "" ).split( "." ).sort();
  60. // If event changes its type, use the special event handlers for the changed type
  61. special = jQuery.event.special[ type ] || {};
  62. // If selector defined, determine special event api type, otherwise given type
  63. type = ( selector ? special.delegateType : special.bindType ) || type;
  64. // Update special based on newly reset type
  65. special = jQuery.event.special[ type ] || {};
  66. // handleObj is passed to all event handlers
  67. handleObj = jQuery.extend({
  68. type: type,
  69. origType: origType,
  70. data: data,
  71. handler: handler,
  72. guid: handler.guid,
  73. selector: selector,
  74. needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
  75. namespace: namespaces.join(".")
  76. }, handleObjIn );
  77. // Init the event handler queue if we're the first
  78. if ( !(handlers = events[ type ]) ) {
  79. handlers = events[ type ] = [];
  80. handlers.delegateCount = 0;
  81. // Only use addEventListener/attachEvent if the special events handler returns false
  82. if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
  83. // Bind the global event handler to the element
  84. if ( elem.addEventListener ) {
  85. elem.addEventListener( type, eventHandle, false );
  86. } else if ( elem.attachEvent ) {
  87. elem.attachEvent( "on" + type, eventHandle );
  88. }
  89. }
  90. }
  91. if ( special.add ) {
  92. special.add.call( elem, handleObj );
  93. if ( !handleObj.handler.guid ) {
  94. handleObj.handler.guid = handler.guid;
  95. }
  96. }
  97. // Add to the element's handler list, delegates in front
  98. if ( selector ) {
  99. handlers.splice( handlers.delegateCount++, 0, handleObj );
  100. } else {
  101. handlers.push( handleObj );
  102. }
  103. // Keep track of which events have ever been used, for event optimization
  104. jQuery.event.global[ type ] = true;
  105. }
  106. // Nullify elem to prevent memory leaks in IE
  107. elem = null;
  108. },
  109. // Detach an event or set of events from an element
  110. remove: function( elem, types, handler, selector, mappedTypes ) {
  111. var j, handleObj, tmp,
  112. origCount, t, events,
  113. special, handlers, type,
  114. namespaces, origType,
  115. elemData = jQuery.hasData( elem ) && jQuery._data( elem );
  116. if ( !elemData || !(events = elemData.events) ) {
  117. return;
  118. }
  119. // Once for each type.namespace in types; type may be omitted
  120. types = ( types || "" ).match( core_rnotwhite ) || [""];
  121. t = types.length;
  122. while ( t-- ) {
  123. tmp = rtypenamespace.exec( types[t] ) || [];
  124. type = origType = tmp[1];
  125. namespaces = ( tmp[2] || "" ).split( "." ).sort();
  126. // Unbind all events (on this namespace, if provided) for the element
  127. if ( !type ) {
  128. for ( type in events ) {
  129. jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
  130. }
  131. continue;
  132. }
  133. special = jQuery.event.special[ type ] || {};
  134. type = ( selector ? special.delegateType : special.bindType ) || type;
  135. handlers = events[ type ] || [];
  136. tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
  137. // Remove matching events
  138. origCount = j = handlers.length;
  139. while ( j-- ) {
  140. handleObj = handlers[ j ];
  141. if ( ( mappedTypes || origType === handleObj.origType ) &&
  142. ( !handler || handler.guid === handleObj.guid ) &&
  143. ( !tmp || tmp.test( handleObj.namespace ) ) &&
  144. ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
  145. handlers.splice( j, 1 );
  146. if ( handleObj.selector ) {
  147. handlers.delegateCount--;
  148. }
  149. if ( special.remove ) {
  150. special.remove.call( elem, handleObj );
  151. }
  152. }
  153. }
  154. // Remove generic event handler if we removed something and no more handlers exist
  155. // (avoids potential for endless recursion during removal of special event handlers)
  156. if ( origCount && !handlers.length ) {
  157. if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
  158. jQuery.removeEvent( elem, type, elemData.handle );
  159. }
  160. delete events[ type ];
  161. }
  162. }
  163. // Remove the expando if it's no longer used
  164. if ( jQuery.isEmptyObject( events ) ) {
  165. delete elemData.handle;
  166. // removeData also checks for emptiness and clears the expando if empty
  167. // so use it instead of delete
  168. jQuery._removeData( elem, "events" );
  169. }
  170. },
  171. trigger: function( event, data, elem, onlyHandlers ) {
  172. var handle, ontype, cur,
  173. bubbleType, special, tmp, i,
  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. event.isTrigger = true;
  198. event.namespace = namespaces.join(".");
  199. event.namespace_re = event.namespace ?
  200. new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
  201. null;
  202. // Clean up the event in case it is being reused
  203. event.result = undefined;
  204. if ( !event.target ) {
  205. event.target = elem;
  206. }
  207. // Clone any incoming data and prepend the event, creating the handler arg list
  208. data = data == null ?
  209. [ event ] :
  210. jQuery.makeArray( data, [ event ] );
  211. // Allow special events to draw outside the lines
  212. special = jQuery.event.special[ type ] || {};
  213. if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
  214. return;
  215. }
  216. // Determine event propagation path in advance, per W3C events spec (#9951)
  217. // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
  218. if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
  219. bubbleType = special.delegateType || type;
  220. if ( !rfocusMorph.test( bubbleType + type ) ) {
  221. cur = cur.parentNode;
  222. }
  223. for ( ; cur; cur = cur.parentNode ) {
  224. eventPath.push( cur );
  225. tmp = cur;
  226. }
  227. // Only add window if we got to document (e.g., not plain obj or detached DOM)
  228. if ( tmp === (elem.ownerDocument || document) ) {
  229. eventPath.push( tmp.defaultView || tmp.parentWindow || window );
  230. }
  231. }
  232. // Fire handlers on the event path
  233. i = 0;
  234. while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
  235. event.type = i > 1 ?
  236. bubbleType :
  237. special.bindType || type;
  238. // jQuery handler
  239. handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
  240. if ( handle ) {
  241. handle.apply( cur, data );
  242. }
  243. // Native handler
  244. handle = ontype && cur[ ontype ];
  245. if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
  246. event.preventDefault();
  247. }
  248. }
  249. event.type = type;
  250. // If nobody prevented the default action, do it now
  251. if ( !onlyHandlers && !event.isDefaultPrevented() ) {
  252. if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
  253. !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
  254. // Call a native DOM method on the target with the same name name as the event.
  255. // Can't use an .isFunction() check here because IE6/7 fails that test.
  256. // Don't do default actions on window, that's where global variables be (#6170)
  257. if ( ontype && 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. try {
  266. elem[ type ]();
  267. } catch ( e ) {
  268. // IE<9 dies on focus/blur to hidden element (#1486,#12518)
  269. // only reproducible on winXP IE8 native, not IE9 in IE8 mode
  270. }
  271. jQuery.event.triggered = undefined;
  272. if ( tmp ) {
  273. elem[ ontype ] = tmp;
  274. }
  275. }
  276. }
  277. }
  278. return event.result;
  279. },
  280. dispatch: function( event ) {
  281. // Make a writable jQuery.Event from the native event object
  282. event = jQuery.event.fix( event );
  283. var i, ret, handleObj, matched, j,
  284. handlerQueue = [],
  285. args = core_slice.call( arguments ),
  286. handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
  287. special = jQuery.event.special[ event.type ] || {};
  288. // Use the fix-ed jQuery.Event rather than the (read-only) native event
  289. args[0] = event;
  290. event.delegateTarget = this;
  291. // Call the preDispatch hook for the mapped type, and let it bail if desired
  292. if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
  293. return;
  294. }
  295. // Determine handlers
  296. handlerQueue = jQuery.event.handlers.call( this, event, handlers );
  297. // Run delegates first; they may want to stop propagation beneath us
  298. i = 0;
  299. while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
  300. event.currentTarget = matched.elem;
  301. j = 0;
  302. while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
  303. // Triggered event must either 1) have no namespace, or
  304. // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
  305. if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
  306. event.handleObj = handleObj;
  307. event.data = handleObj.data;
  308. ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
  309. .apply( matched.elem, args );
  310. if ( ret !== undefined ) {
  311. if ( (event.result = ret) === false ) {
  312. event.preventDefault();
  313. event.stopPropagation();
  314. }
  315. }
  316. }
  317. }
  318. }
  319. // Call the postDispatch hook for the mapped type
  320. if ( special.postDispatch ) {
  321. special.postDispatch.call( this, event );
  322. }
  323. return event.result;
  324. },
  325. handlers: function( event, handlers ) {
  326. var sel, handleObj, matches, i,
  327. handlerQueue = [],
  328. delegateCount = handlers.delegateCount,
  329. cur = event.target;
  330. // Find delegate handlers
  331. // Black-hole SVG <use> instance trees (#13180)
  332. // Avoid non-left-click bubbling in Firefox (#3861)
  333. if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
  334. for ( ; cur != this; cur = cur.parentNode || this ) {
  335. // Don't check non-elements (#13208)
  336. // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
  337. if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
  338. matches = [];
  339. for ( i = 0; i < delegateCount; i++ ) {
  340. handleObj = handlers[ i ];
  341. // Don't conflict with Object.prototype properties (#13203)
  342. sel = handleObj.selector + " ";
  343. if ( matches[ sel ] === undefined ) {
  344. matches[ sel ] = handleObj.needsContext ?
  345. jQuery( sel, this ).index( cur ) >= 0 :
  346. jQuery.find( sel, this, null, [ cur ] ).length;
  347. }
  348. if ( matches[ sel ] ) {
  349. matches.push( handleObj );
  350. }
  351. }
  352. if ( matches.length ) {
  353. handlerQueue.push({ elem: cur, handlers: matches });
  354. }
  355. }
  356. }
  357. }
  358. // Add the remaining (directly-bound) handlers
  359. if ( delegateCount < handlers.length ) {
  360. handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
  361. }
  362. return handlerQueue;
  363. },
  364. fix: function( event ) {
  365. if ( event[ jQuery.expando ] ) {
  366. return event;
  367. }
  368. // Create a writable copy of the event object and normalize some properties
  369. var i, prop, copy,
  370. type = event.type,
  371. originalEvent = event,
  372. fixHook = this.fixHooks[ type ];
  373. if ( !fixHook ) {
  374. this.fixHooks[ type ] = fixHook =
  375. rmouseEvent.test( type ) ? this.mouseHooks :
  376. rkeyEvent.test( type ) ? this.keyHooks :
  377. {};
  378. }
  379. copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
  380. event = new jQuery.Event( originalEvent );
  381. i = copy.length;
  382. while ( i-- ) {
  383. prop = copy[ i ];
  384. event[ prop ] = originalEvent[ prop ];
  385. }
  386. // Support: IE<9
  387. // Fix target property (#1925)
  388. if ( !event.target ) {
  389. event.target = originalEvent.srcElement || document;
  390. }
  391. // Support: Chrome 23+, Safari?
  392. // Target should not be a text node (#504, #13143)
  393. if ( event.target.nodeType === 3 ) {
  394. event.target = event.target.parentNode;
  395. }
  396. // Support: IE<9
  397. // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
  398. event.metaKey = !!event.metaKey;
  399. return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
  400. },
  401. // Includes some event props shared by KeyEvent and MouseEvent
  402. props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
  403. fixHooks: {},
  404. keyHooks: {
  405. props: "char charCode key keyCode".split(" "),
  406. filter: function( event, original ) {
  407. // Add which for key events
  408. if ( event.which == null ) {
  409. event.which = original.charCode != null ? original.charCode : original.keyCode;
  410. }
  411. return event;
  412. }
  413. },
  414. mouseHooks: {
  415. props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
  416. filter: function( event, original ) {
  417. var body, eventDoc, doc,
  418. button = original.button,
  419. fromElement = original.fromElement;
  420. // Calculate pageX/Y if missing and clientX/Y available
  421. if ( event.pageX == null && original.clientX != null ) {
  422. eventDoc = event.target.ownerDocument || document;
  423. doc = eventDoc.documentElement;
  424. body = eventDoc.body;
  425. event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
  426. event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
  427. }
  428. // Add relatedTarget, if necessary
  429. if ( !event.relatedTarget && fromElement ) {
  430. event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
  431. }
  432. // Add which for click: 1 === left; 2 === middle; 3 === right
  433. // Note: button is not normalized, so don't use it
  434. if ( !event.which && button !== undefined ) {
  435. event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
  436. }
  437. return event;
  438. }
  439. },
  440. special: {
  441. load: {
  442. // Prevent triggered image.load events from bubbling to window.load
  443. noBubble: true
  444. },
  445. click: {
  446. // For checkbox, fire native event so checked state will be right
  447. trigger: function() {
  448. if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
  449. this.click();
  450. return false;
  451. }
  452. }
  453. },
  454. focus: {
  455. // Fire native event if possible so blur/focus sequence is correct
  456. trigger: function() {
  457. if ( this !== document.activeElement && this.focus ) {
  458. try {
  459. this.focus();
  460. return false;
  461. } catch ( e ) {
  462. // Support: IE<9
  463. // If we error on focus to hidden element (#1486, #12518),
  464. // let .trigger() run the handlers
  465. }
  466. }
  467. },
  468. delegateType: "focusin"
  469. },
  470. blur: {
  471. trigger: function() {
  472. if ( this === document.activeElement && this.blur ) {
  473. this.blur();
  474. return false;
  475. }
  476. },
  477. delegateType: "focusout"
  478. },
  479. beforeunload: {
  480. postDispatch: function( event ) {
  481. // Even when returnValue equals to undefined Firefox will still show alert
  482. if ( event.result !== undefined ) {
  483. event.originalEvent.returnValue = event.result;
  484. }
  485. }
  486. }
  487. },
  488. simulate: function( type, elem, event, bubble ) {
  489. // Piggyback on a donor event to simulate a different one.
  490. // Fake originalEvent to avoid donor's stopPropagation, but if the
  491. // simulated event prevents default then we do the same on the donor.
  492. var e = jQuery.extend(
  493. new jQuery.Event(),
  494. event,
  495. { type: type,
  496. isSimulated: true,
  497. originalEvent: {}
  498. }
  499. );
  500. if ( bubble ) {
  501. jQuery.event.trigger( e, null, elem );
  502. } else {
  503. jQuery.event.dispatch.call( elem, e );
  504. }
  505. if ( e.isDefaultPrevented() ) {
  506. event.preventDefault();
  507. }
  508. }
  509. };
  510. jQuery.removeEvent = document.removeEventListener ?
  511. function( elem, type, handle ) {
  512. if ( elem.removeEventListener ) {
  513. elem.removeEventListener( type, handle, false );
  514. }
  515. } :
  516. function( elem, type, handle ) {
  517. var name = "on" + type;
  518. if ( elem.detachEvent ) {
  519. // #8545, #7054, preventing memory leaks for custom events in IE6-8
  520. // detachEvent needed property on element, by name of that event, to properly expose it to GC
  521. if ( typeof elem[ name ] === core_strundefined ) {
  522. elem[ name ] = null;
  523. }
  524. elem.detachEvent( name, handle );
  525. }
  526. };
  527. jQuery.Event = function( src, props ) {
  528. // Allow instantiation without the 'new' keyword
  529. if ( !(this instanceof jQuery.Event) ) {
  530. return new jQuery.Event( src, props );
  531. }
  532. // Event object
  533. if ( src && src.type ) {
  534. this.originalEvent = src;
  535. this.type = src.type;
  536. // Events bubbling up the document may have been marked as prevented
  537. // by a handler lower down the tree; reflect the correct value.
  538. this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
  539. src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
  540. // Event type
  541. } else {
  542. this.type = src;
  543. }
  544. // Put explicitly provided properties onto the event object
  545. if ( props ) {
  546. jQuery.extend( this, props );
  547. }
  548. // Create a timestamp if incoming event doesn't have one
  549. this.timeStamp = src && src.timeStamp || jQuery.now();
  550. // Mark it as fixed
  551. this[ jQuery.expando ] = true;
  552. };
  553. // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
  554. // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
  555. jQuery.Event.prototype = {
  556. isDefaultPrevented: returnFalse,
  557. isPropagationStopped: returnFalse,
  558. isImmediatePropagationStopped: returnFalse,
  559. preventDefault: function() {
  560. var e = this.originalEvent;
  561. this.isDefaultPrevented = returnTrue;
  562. if ( !e ) {
  563. return;
  564. }
  565. // If preventDefault exists, run it on the original event
  566. if ( e.preventDefault ) {
  567. e.preventDefault();
  568. // Support: IE
  569. // Otherwise set the returnValue property of the original event to false
  570. } else {
  571. e.returnValue = false;
  572. }
  573. },
  574. stopPropagation: function() {
  575. var e = this.originalEvent;
  576. this.isPropagationStopped = returnTrue;
  577. if ( !e ) {
  578. return;
  579. }
  580. // If stopPropagation exists, run it on the original event
  581. if ( e.stopPropagation ) {
  582. e.stopPropagation();
  583. }
  584. // Support: IE
  585. // Set the cancelBubble property of the original event to true
  586. e.cancelBubble = true;
  587. },
  588. stopImmediatePropagation: function() {
  589. this.isImmediatePropagationStopped = returnTrue;
  590. this.stopPropagation();
  591. }
  592. };
  593. // Create mouseenter/leave events using mouseover/out and event-time checks
  594. jQuery.each({
  595. mouseenter: "mouseover",
  596. mouseleave: "mouseout"
  597. }, function( orig, fix ) {
  598. jQuery.event.special[ orig ] = {
  599. delegateType: fix,
  600. bindType: fix,
  601. handle: function( event ) {
  602. var ret,
  603. target = this,
  604. related = event.relatedTarget,
  605. handleObj = event.handleObj;
  606. // For mousenter/leave call the handler if related is outside the target.
  607. // NB: No relatedTarget if the mouse left/entered the browser window
  608. if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
  609. event.type = handleObj.origType;
  610. ret = handleObj.handler.apply( this, arguments );
  611. event.type = fix;
  612. }
  613. return ret;
  614. }
  615. };
  616. });
  617. // IE submit delegation
  618. if ( !jQuery.support.submitBubbles ) {
  619. jQuery.event.special.submit = {
  620. setup: function() {
  621. // Only need this for delegated form submit events
  622. if ( jQuery.nodeName( this, "form" ) ) {
  623. return false;
  624. }
  625. // Lazy-add a submit handler when a descendant form may potentially be submitted
  626. jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
  627. // Node name check avoids a VML-related crash in IE (#9807)
  628. var elem = e.target,
  629. form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
  630. if ( form && !jQuery._data( form, "submitBubbles" ) ) {
  631. jQuery.event.add( form, "submit._submit", function( event ) {
  632. event._submit_bubble = true;
  633. });
  634. jQuery._data( form, "submitBubbles", true );
  635. }
  636. });
  637. // return undefined since we don't need an event listener
  638. },
  639. postDispatch: function( event ) {
  640. // If form was submitted by the user, bubble the event up the tree
  641. if ( event._submit_bubble ) {
  642. delete event._submit_bubble;
  643. if ( this.parentNode && !event.isTrigger ) {
  644. jQuery.event.simulate( "submit", this.parentNode, event, true );
  645. }
  646. }
  647. },
  648. teardown: function() {
  649. // Only need this for delegated form submit events
  650. if ( jQuery.nodeName( this, "form" ) ) {
  651. return false;
  652. }
  653. // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
  654. jQuery.event.remove( this, "._submit" );
  655. }
  656. };
  657. }
  658. // IE change delegation and checkbox/radio fix
  659. if ( !jQuery.support.changeBubbles ) {
  660. jQuery.event.special.change = {
  661. setup: function() {
  662. if ( rformElems.test( this.nodeName ) ) {
  663. // IE doesn't fire change on a check/radio until blur; trigger it on click
  664. // after a propertychange. Eat the blur-change in special.change.handle.
  665. // This still fires onchange a second time for check/radio after blur.
  666. if ( this.type === "checkbox" || this.type === "radio" ) {
  667. jQuery.event.add( this, "propertychange._change", function( event ) {
  668. if ( event.originalEvent.propertyName === "checked" ) {
  669. this._just_changed = true;
  670. }
  671. });
  672. jQuery.event.add( this, "click._change", function( event ) {
  673. if ( this._just_changed && !event.isTrigger ) {
  674. this._just_changed = false;
  675. }
  676. // Allow triggered, simulated change events (#11500)
  677. jQuery.event.simulate( "change", this, event, true );
  678. });
  679. }
  680. return false;
  681. }
  682. // Delegated event; lazy-add a change handler on descendant inputs
  683. jQuery.event.add( this, "beforeactivate._change", function( e ) {
  684. var elem = e.target;
  685. if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
  686. jQuery.event.add( elem, "change._change", function( event ) {
  687. if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
  688. jQuery.event.simulate( "change", this.parentNode, event, true );
  689. }
  690. });
  691. jQuery._data( elem, "changeBubbles", true );
  692. }
  693. });
  694. },
  695. handle: function( event ) {
  696. var elem = event.target;
  697. // Swallow native change events from checkbox/radio, we already triggered them above
  698. if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
  699. return event.handleObj.handler.apply( this, arguments );
  700. }
  701. },
  702. teardown: function() {
  703. jQuery.event.remove( this, "._change" );
  704. return !rformElems.test( this.nodeName );
  705. }
  706. };
  707. }
  708. // Create "bubbling" focus and blur events
  709. if ( !jQuery.support.focusinBubbles ) {
  710. jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
  711. // Attach a single capturing handler while someone wants focusin/focusout
  712. var attaches = 0,
  713. handler = function( event ) {
  714. jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
  715. };
  716. jQuery.event.special[ fix ] = {
  717. setup: function() {
  718. if ( attaches++ === 0 ) {
  719. document.addEventListener( orig, handler, true );
  720. }
  721. },
  722. teardown: function() {
  723. if ( --attaches === 0 ) {
  724. document.removeEventListener( orig, handler, true );
  725. }
  726. }
  727. };
  728. });
  729. }
  730. jQuery.fn.extend({
  731. on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
  732. var type, origFn;
  733. // Types can be a map of types/handlers
  734. if ( typeof types === "object" ) {
  735. // ( types-Object, selector, data )
  736. if ( typeof selector !== "string" ) {
  737. // ( types-Object, data )
  738. data = data || selector;
  739. selector = undefined;
  740. }
  741. for ( type in types ) {
  742. this.on( type, selector, data, types[ type ], one );
  743. }
  744. return this;
  745. }
  746. if ( data == null && fn == null ) {
  747. // ( types, fn )
  748. fn = selector;
  749. data = selector = undefined;
  750. } else if ( fn == null ) {
  751. if ( typeof selector === "string" ) {
  752. // ( types, selector, fn )
  753. fn = data;
  754. data = undefined;
  755. } else {
  756. // ( types, data, fn )
  757. fn = data;
  758. data = selector;
  759. selector = undefined;
  760. }
  761. }
  762. if ( fn === false ) {
  763. fn = returnFalse;
  764. } else if ( !fn ) {
  765. return this;
  766. }
  767. if ( one === 1 ) {
  768. origFn = fn;
  769. fn = function( event ) {
  770. // Can use an empty set, since event contains the info
  771. jQuery().off( event );
  772. return origFn.apply( this, arguments );
  773. };
  774. // Use same guid so caller can remove using origFn
  775. fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
  776. }
  777. return this.each( function() {
  778. jQuery.event.add( this, types, fn, data, selector );
  779. });
  780. },
  781. one: function( types, selector, data, fn ) {
  782. return this.on( types, selector, data, fn, 1 );
  783. },
  784. off: function( types, selector, fn ) {
  785. var handleObj, type;
  786. if ( types && types.preventDefault && types.handleObj ) {
  787. // ( event ) dispatched jQuery.Event
  788. handleObj = types.handleObj;
  789. jQuery( types.delegateTarget ).off(
  790. handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
  791. handleObj.selector,
  792. handleObj.handler
  793. );
  794. return this;
  795. }
  796. if ( typeof types === "object" ) {
  797. // ( types-object [, selector] )
  798. for ( type in types ) {
  799. this.off( type, selector, types[ type ] );
  800. }
  801. return this;
  802. }
  803. if ( selector === false || typeof selector === "function" ) {
  804. // ( types [, fn] )
  805. fn = selector;
  806. selector = undefined;
  807. }
  808. if ( fn === false ) {
  809. fn = returnFalse;
  810. }
  811. return this.each(function() {
  812. jQuery.event.remove( this, types, fn, selector );
  813. });
  814. },
  815. bind: function( types, data, fn ) {
  816. return this.on( types, null, data, fn );
  817. },
  818. unbind: function( types, fn ) {
  819. return this.off( types, null, fn );
  820. },
  821. delegate: function( selector, types, data, fn ) {
  822. return this.on( types, selector, data, fn );
  823. },
  824. undelegate: function( selector, types, fn ) {
  825. // ( namespace ) or ( selector, types [, fn] )
  826. return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
  827. },
  828. trigger: function( type, data ) {
  829. return this.each(function() {
  830. jQuery.event.trigger( type, data, this );
  831. });
  832. },
  833. triggerHandler: function( type, data ) {
  834. var elem = this[0];
  835. if ( elem ) {
  836. return jQuery.event.trigger( type, data, elem, true );
  837. }
  838. }
  839. });