Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14217 anikendra 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
});