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