Fix tabs vs spaces in initial workaround commit
[jquery.git] / src / event.js
1 (function( jQuery ) {
2
3 var rnamespaces = /\.(.*)$/,
4         rformElems = /^(?:textarea|input|select)$/i,
5         rperiod = /\./g,
6         rspace = / /g,
7         rescape = /[^\w\s.|`]/g,
8         fcleanup = function( nm ) {
9                 return nm.replace(rescape, "\\$&");
10         },
11         focusCounts = { focusin: 0, focusout: 0 };
12
13 /*
14  * A number of helper functions used for managing events.
15  * Many of the ideas behind this code originated from
16  * Dean Edwards' addEvent library.
17  */
18 jQuery.event = {
19
20         // Bind an event to an element
21         // Original by Dean Edwards
22         add: function( elem, types, handler, data ) {
23                 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
24                         return;
25                 }
26
27                 // For whatever reason, IE has trouble passing the window object
28                 // around, causing it to be cloned in the process
29                 if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) {
30                         elem = window;
31                 }
32
33                 if ( handler === false ) {
34                         handler = returnFalse;
35                 } else if ( !handler ) {
36                         // Fixes bug #7229. Fix recommended by jdalton
37                   return;
38                 }
39
40                 var handleObjIn, handleObj;
41
42                 if ( handler.handler ) {
43                         handleObjIn = handler;
44                         handler = handleObjIn.handler;
45                 }
46
47                 // Make sure that the function being executed has a unique ID
48                 if ( !handler.guid ) {
49                         handler.guid = jQuery.guid++;
50                 }
51
52                 // Init the element's event structure
53                 var elemData = jQuery.data( elem );
54
55                 // If no elemData is found then we must be trying to bind to one of the
56                 // banned noData elements
57                 if ( !elemData ) {
58                         return;
59                 }
60
61                 // Use a key less likely to result in collisions for plain JS objects.
62                 // Fixes bug #7150.
63                 var eventKey = elem.nodeType ? "events" : "__events__",
64                         events = elemData[ eventKey ],
65                         eventHandle = elemData.handle;
66
67                 if ( typeof events === "function" ) {
68                         // On plain objects events is a fn that holds the the data
69                         // which prevents this data from being JSON serialized
70                         // the function does not need to be called, it just contains the data
71                         eventHandle = events.handle;
72                         events = events.events;
73
74                 } else if ( !events ) {
75                         if ( !elem.nodeType ) {
76                                 // On plain objects, create a fn that acts as the holder
77                                 // of the values to avoid JSON serialization of event data
78                                 elemData[ eventKey ] = elemData = function(){};
79                         }
80
81                         elemData.events = events = {};
82                 }
83
84                 if ( !eventHandle ) {
85                         elemData.handle = eventHandle = function() {
86                                 // Handle the second event of a trigger and when
87                                 // an event is called after a page has unloaded
88                                 return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
89                                         jQuery.event.handle.apply( eventHandle.elem, arguments ) :
90                                         undefined;
91                         };
92                 }
93
94                 // Add elem as a property of the handle function
95                 // This is to prevent a memory leak with non-native events in IE.
96                 eventHandle.elem = elem;
97
98                 // Handle multiple events separated by a space
99                 // jQuery(...).bind("mouseover mouseout", fn);
100                 types = types.split(" ");
101
102                 var type, i = 0, namespaces;
103
104                 while ( (type = types[ i++ ]) ) {
105                         handleObj = handleObjIn ?
106                                 jQuery.extend({}, handleObjIn) :
107                                 { handler: handler, data: data };
108
109                         // Namespaced event handlers
110                         if ( type.indexOf(".") > -1 ) {
111                                 namespaces = type.split(".");
112                                 type = namespaces.shift();
113                                 handleObj.namespace = namespaces.slice(0).sort().join(".");
114
115                         } else {
116                                 namespaces = [];
117                                 handleObj.namespace = "";
118                         }
119
120                         handleObj.type = type;
121                         if ( !handleObj.guid ) {
122                                 handleObj.guid = handler.guid;
123                         }
124
125                         // Get the current list of functions bound to this event
126                         var handlers = events[ type ],
127                                 special = jQuery.event.special[ type ] || {};
128
129                         // Init the event handler queue
130                         if ( !handlers ) {
131                                 handlers = events[ type ] = [];
132
133                                 // Check for a special event handler
134                                 // Only use addEventListener/attachEvent if the special
135                                 // events handler returns false
136                                 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
137                                         // Bind the global event handler to the element
138                                         if ( elem.addEventListener ) {
139                                                 elem.addEventListener( type, eventHandle, false );
140
141                                         } else if ( elem.attachEvent ) {
142                                                 elem.attachEvent( "on" + type, eventHandle );
143                                         }
144                                 }
145                         }
146
147                         if ( special.add ) {
148                                 special.add.call( elem, handleObj );
149
150                                 if ( !handleObj.handler.guid ) {
151                                         handleObj.handler.guid = handler.guid;
152                                 }
153                         }
154
155                         // Add the function to the element's handler list
156                         handlers.push( handleObj );
157
158                         // Keep track of which events have been used, for global triggering
159                         jQuery.event.global[ type ] = true;
160                 }
161
162                 // Nullify elem to prevent memory leaks in IE
163                 elem = null;
164         },
165
166         global: {},
167
168         // Detach an event or set of events from an element
169         remove: function( elem, types, handler, pos ) {
170                 // don't do events on text and comment nodes
171                 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
172                         return;
173                 }
174
175                 if ( handler === false ) {
176                         handler = returnFalse;
177                 }
178
179                 var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
180                         eventKey = elem.nodeType ? "events" : "__events__",
181                         elemData = jQuery.data( elem ),
182                         events = elemData && elemData[ eventKey ];
183
184                 if ( !elemData || !events ) {
185                         return;
186                 }
187
188                 if ( typeof events === "function" ) {
189                         elemData = events;
190                         events = events.events;
191                 }
192
193                 // types is actually an event object here
194                 if ( types && types.type ) {
195                         handler = types.handler;
196                         types = types.type;
197                 }
198
199                 // Unbind all events for the element
200                 if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
201                         types = types || "";
202
203                         for ( type in events ) {
204                                 jQuery.event.remove( elem, type + types );
205                         }
206
207                         return;
208                 }
209
210                 // Handle multiple events separated by a space
211                 // jQuery(...).unbind("mouseover mouseout", fn);
212                 types = types.split(" ");
213
214                 while ( (type = types[ i++ ]) ) {
215                         origType = type;
216                         handleObj = null;
217                         all = type.indexOf(".") < 0;
218                         namespaces = [];
219
220                         if ( !all ) {
221                                 // Namespaced event handlers
222                                 namespaces = type.split(".");
223                                 type = namespaces.shift();
224
225                                 namespace = new RegExp("(^|\\.)" +
226                                         jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
227                         }
228
229                         eventType = events[ type ];
230
231                         if ( !eventType ) {
232                                 continue;
233                         }
234
235                         if ( !handler ) {
236                                 for ( j = 0; j < eventType.length; j++ ) {
237                                         handleObj = eventType[ j ];
238
239                                         if ( all || namespace.test( handleObj.namespace ) ) {
240                                                 jQuery.event.remove( elem, origType, handleObj.handler, j );
241                                                 eventType.splice( j--, 1 );
242                                         }
243                                 }
244
245                                 continue;
246                         }
247
248                         special = jQuery.event.special[ type ] || {};
249
250                         for ( j = pos || 0; j < eventType.length; j++ ) {
251                                 handleObj = eventType[ j ];
252
253                                 if ( handler.guid === handleObj.guid ) {
254                                         // remove the given handler for the given type
255                                         if ( all || namespace.test( handleObj.namespace ) ) {
256                                                 if ( pos == null ) {
257                                                         eventType.splice( j--, 1 );
258                                                 }
259
260                                                 if ( special.remove ) {
261                                                         special.remove.call( elem, handleObj );
262                                                 }
263                                         }
264
265                                         if ( pos != null ) {
266                                                 break;
267                                         }
268                                 }
269                         }
270
271                         // remove generic event handler if no more handlers exist
272                         if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
273                                 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
274                                         jQuery.removeEvent( elem, type, elemData.handle );
275                                 }
276
277                                 ret = null;
278                                 delete events[ type ];
279                         }
280                 }
281
282                 // Remove the expando if it's no longer used
283                 if ( jQuery.isEmptyObject( events ) ) {
284                         var handle = elemData.handle;
285                         if ( handle ) {
286                                 handle.elem = null;
287                         }
288
289                         delete elemData.events;
290                         delete elemData.handle;
291
292                         if ( typeof elemData === "function" ) {
293                                 jQuery.removeData( elem, eventKey );
294
295                         } else if ( jQuery.isEmptyObject( elemData ) ) {
296                                 jQuery.removeData( elem );
297                         }
298                 }
299         },
300
301         // bubbling is internal
302         trigger: function( event, data, elem /*, bubbling */ ) {
303                 // Event object or event type
304                 var type = event.type || event,
305                         bubbling = arguments[3];
306
307                 if ( !bubbling ) {
308                         event = typeof event === "object" ?
309                                 // jQuery.Event object
310                                 event[ jQuery.expando ] ? event :
311                                 // Object literal
312                                 jQuery.extend( jQuery.Event(type), event ) :
313                                 // Just the event type (string)
314                                 jQuery.Event(type);
315
316                         if ( type.indexOf("!") >= 0 ) {
317                                 event.type = type = type.slice(0, -1);
318                                 event.exclusive = true;
319                         }
320
321                         // Handle a global trigger
322                         if ( !elem ) {
323                                 // Don't bubble custom events when global (to avoid too much overhead)
324                                 event.stopPropagation();
325
326                                 // Only trigger if we've ever bound an event for it
327                                 if ( jQuery.event.global[ type ] ) {
328                                         jQuery.each( jQuery.cache, function() {
329                                                 if ( this.events && this.events[type] ) {
330                                                         jQuery.event.trigger( event, data, this.handle.elem );
331                                                 }
332                                         });
333                                 }
334                         }
335
336                         // Handle triggering a single element
337
338                         // don't do events on text and comment nodes
339                         if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
340                                 return undefined;
341                         }
342
343                         // Clean up in case it is reused
344                         event.result = undefined;
345                         event.target = elem;
346
347                         // Clone the incoming data, if any
348                         data = jQuery.makeArray( data );
349                         data.unshift( event );
350                 }
351
352                 event.currentTarget = elem;
353
354                 // Trigger the event, it is assumed that "handle" is a function
355                 var handle = elem.nodeType ?
356                         jQuery.data( elem, "handle" ) :
357                         (jQuery.data( elem, "__events__" ) || {}).handle;
358
359                 if ( handle ) {
360                         handle.apply( elem, data );
361                 }
362
363                 var parent = elem.parentNode || elem.ownerDocument;
364
365                 // Trigger an inline bound script
366                 try {
367                         if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
368                                 if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
369                                         event.result = false;
370                                         event.preventDefault();
371                                 }
372                         }
373
374                 // prevent IE from throwing an error for some elements with some event types, see #3533
375                 } catch (inlineError) {}
376
377                 if ( !event.isPropagationStopped() && parent ) {
378                         jQuery.event.trigger( event, data, parent, true );
379
380                 } else if ( !event.isDefaultPrevented() ) {
381                         var old,
382                                 target = event.target,
383                                 targetType = type.replace( rnamespaces, "" ),
384                                 isClick = jQuery.nodeName( target, "a" ) && targetType === "click",
385                                 special = jQuery.event.special[ targetType ] || {};
386
387                         if ( (!special._default || special._default.call( elem, event ) === false) &&
388                                 !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
389
390                                 try {
391                                         if ( target[ targetType ] ) {
392                                                 // Make sure that we don't accidentally re-trigger the onFOO events
393                                                 old = target[ "on" + targetType ];
394
395                                                 if ( old ) {
396                                                         target[ "on" + targetType ] = null;
397                                                 }
398
399                                                 jQuery.event.triggered = true;
400                                                 target[ targetType ]();
401                                         }
402
403                                 // prevent IE from throwing an error for some elements with some event types, see #3533
404                                 } catch (triggerError) {}
405
406                                 if ( old ) {
407                                         target[ "on" + targetType ] = old;
408                                 }
409
410                                 jQuery.event.triggered = false;
411                         }
412                 }
413         },
414
415         handle: function( event ) {
416                 var all, handlers, namespaces, namespace_re, events,
417                         namespace_sort = [],
418                         args = jQuery.makeArray( arguments );
419
420                 event = args[0] = jQuery.event.fix( event || window.event );
421                 event.currentTarget = this;
422
423                 // Namespaced event handlers
424                 all = event.type.indexOf(".") < 0 && !event.exclusive;
425
426                 if ( !all ) {
427                         namespaces = event.type.split(".");
428                         event.type = namespaces.shift();
429                         namespace_sort = namespaces.slice(0).sort();
430                         namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
431                 }
432
433                 event.namespace = event.namespace || namespace_sort.join(".");
434
435                 events = jQuery.data(this, this.nodeType ? "events" : "__events__");
436
437                 if ( typeof events === "function" ) {
438                         events = events.events;
439                 }
440
441                 handlers = (events || {})[ event.type ];
442
443                 if ( events && handlers ) {
444                         // Clone the handlers to prevent manipulation
445                         handlers = handlers.slice(0);
446
447                         for ( var j = 0, l = handlers.length; j < l; j++ ) {
448                                 var handleObj = handlers[ j ];
449
450                                 // Filter the functions by class
451                                 if ( all || namespace_re.test( handleObj.namespace ) ) {
452                                         // Pass in a reference to the handler function itself
453                                         // So that we can later remove it
454                                         event.handler = handleObj.handler;
455                                         event.data = handleObj.data;
456                                         event.handleObj = handleObj;
457
458                                         var ret = handleObj.handler.apply( this, args );
459
460                                         if ( ret !== undefined ) {
461                                                 event.result = ret;
462                                                 if ( ret === false ) {
463                                                         event.preventDefault();
464                                                         event.stopPropagation();
465                                                 }
466                                         }
467
468                                         if ( event.isImmediatePropagationStopped() ) {
469                                                 break;
470                                         }
471                                 }
472                         }
473                 }
474
475                 return event.result;
476         },
477
478         props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
479
480         fix: function( event ) {
481                 if ( event[ jQuery.expando ] ) {
482                         return event;
483                 }
484
485                 // store a copy of the original event object
486                 // and "clone" to set read-only properties
487                 var originalEvent = event;
488                 event = jQuery.Event( originalEvent );
489
490                 for ( var i = this.props.length, prop; i; ) {
491                         prop = this.props[ --i ];
492                         event[ prop ] = originalEvent[ prop ];
493                 }
494
495                 // Fix target property, if necessary
496                 if ( !event.target ) {
497                         // Fixes #1925 where srcElement might not be defined either
498                         event.target = event.srcElement || document;
499                 }
500
501                 // check if target is a textnode (safari)
502                 if ( event.target.nodeType === 3 ) {
503                         event.target = event.target.parentNode;
504                 }
505
506                 // Add relatedTarget, if necessary
507                 if ( !event.relatedTarget && event.fromElement ) {
508                         event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
509                 }
510
511                 // Calculate pageX/Y if missing and clientX/Y available
512                 if ( event.pageX == null && event.clientX != null ) {
513                         var doc = document.documentElement,
514                                 body = document.body;
515
516                         event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
517                         event.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);
518                 }
519
520                 // Add which for key events
521                 if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
522                         event.which = event.charCode != null ? event.charCode : event.keyCode;
523                 }
524
525                 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
526                 if ( !event.metaKey && event.ctrlKey ) {
527                         event.metaKey = event.ctrlKey;
528                 }
529
530                 // Add which for click: 1 === left; 2 === middle; 3 === right
531                 // Note: button is not normalized, so don't use it
532                 if ( !event.which && event.button !== undefined ) {
533                         event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
534                 }
535
536                 return event;
537         },
538
539         // Deprecated, use jQuery.guid instead
540         guid: 1E8,
541
542         // Deprecated, use jQuery.proxy instead
543         proxy: jQuery.proxy,
544
545         special: {
546                 ready: {
547                         // Make sure the ready event is setup
548                         setup: jQuery.bindReady,
549                         teardown: jQuery.noop
550                 },
551
552                 live: {
553                         add: function( handleObj ) {
554                                 jQuery.event.add( this,
555                                         liveConvert( handleObj.origType, handleObj.selector ),
556                                         jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
557                         },
558
559                         remove: function( handleObj ) {
560                                 jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
561                         }
562                 },
563
564                 beforeunload: {
565                         setup: function( data, namespaces, eventHandle ) {
566                                 // We only want to do this special case on windows
567                                 if ( jQuery.isWindow( this ) ) {
568                                         this.onbeforeunload = eventHandle;
569                                 }
570                         },
571
572                         teardown: function( namespaces, eventHandle ) {
573                                 if ( this.onbeforeunload === eventHandle ) {
574                                         this.onbeforeunload = null;
575                                 }
576                         }
577                 }
578         }
579 };
580
581 jQuery.removeEvent = document.removeEventListener ?
582         function( elem, type, handle ) {
583                 if ( elem.removeEventListener ) {
584                         elem.removeEventListener( type, handle, false );
585                 }
586         } :
587         function( elem, type, handle ) {
588                 if ( elem.detachEvent ) {
589                         elem.detachEvent( "on" + type, handle );
590                 }
591         };
592
593 jQuery.Event = function( src ) {
594         // Allow instantiation without the 'new' keyword
595         if ( !this.preventDefault ) {
596                 return new jQuery.Event( src );
597         }
598
599         // Event object
600         if ( src && src.type ) {
601                 this.originalEvent = src;
602                 this.type = src.type;
603
604                 // Events bubbling up the document may have been marked as prevented
605                 // by a handler lower down the tree; reflect the correct value.
606                 this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || 
607                         src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
608
609         // Event type
610         } else {
611                 this.type = src;
612         }
613
614         // timeStamp is buggy for some events on Firefox(#3843)
615         // So we won't rely on the native value
616         this.timeStamp = jQuery.now();
617
618         // Mark it as fixed
619         this[ jQuery.expando ] = true;
620 };
621
622 function returnFalse() {
623         return false;
624 }
625 function returnTrue() {
626         return true;
627 }
628
629 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
630 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
631 jQuery.Event.prototype = {
632         preventDefault: function() {
633                 this.isDefaultPrevented = returnTrue;
634
635                 var e = this.originalEvent;
636                 if ( !e ) {
637                         return;
638                 }
639
640                 // if preventDefault exists run it on the original event
641                 if ( e.preventDefault ) {
642                         e.preventDefault();
643
644                 // otherwise set the returnValue property of the original event to false (IE)
645                 } else {
646                         e.returnValue = false;
647                 }
648         },
649         stopPropagation: function() {
650                 this.isPropagationStopped = returnTrue;
651
652                 var e = this.originalEvent;
653                 if ( !e ) {
654                         return;
655                 }
656                 // if stopPropagation exists run it on the original event
657                 if ( e.stopPropagation ) {
658                         e.stopPropagation();
659                 }
660                 // otherwise set the cancelBubble property of the original event to true (IE)
661                 e.cancelBubble = true;
662         },
663         stopImmediatePropagation: function() {
664                 this.isImmediatePropagationStopped = returnTrue;
665                 this.stopPropagation();
666         },
667         isDefaultPrevented: returnFalse,
668         isPropagationStopped: returnFalse,
669         isImmediatePropagationStopped: returnFalse
670 };
671
672 // Checks if an event happened on an element within another element
673 // Used in jQuery.event.special.mouseenter and mouseleave handlers
674 var withinElement = function( event ) {
675         // Check if mouse(over|out) are still within the same parent element
676         var parent = event.relatedTarget;
677
678         // Firefox sometimes assigns relatedTarget a XUL element
679         // which we cannot access the parentNode property of
680         try {
681                 // Traverse up the tree
682                 while ( parent && parent !== this ) {
683                         parent = parent.parentNode;
684                 }
685
686                 if ( parent !== this ) {
687                         // set the correct event type
688                         event.type = event.data;
689
690                         // handle event if we actually just moused on to a non sub-element
691                         jQuery.event.handle.apply( this, arguments );
692                 }
693
694         // assuming we've left the element since we most likely mousedover a xul element
695         } catch(e) { }
696 },
697
698 // In case of event delegation, we only need to rename the event.type,
699 // liveHandler will take care of the rest.
700 delegate = function( event ) {
701         event.type = event.data;
702         jQuery.event.handle.apply( this, arguments );
703 };
704
705 // Create mouseenter and mouseleave events
706 jQuery.each({
707         mouseenter: "mouseover",
708         mouseleave: "mouseout"
709 }, function( orig, fix ) {
710         jQuery.event.special[ orig ] = {
711                 setup: function( data ) {
712                         jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
713                 },
714                 teardown: function( data ) {
715                         jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
716                 }
717         };
718 });
719
720 // submit delegation
721 if ( !jQuery.support.submitBubbles ) {
722
723         jQuery.event.special.submit = {
724                 setup: function( data, namespaces ) {
725                         if ( this.nodeName && this.nodeName.toLowerCase() !== "form" ) {
726                                 jQuery.event.add(this, "click.specialSubmit", function( e ) {
727                                         var elem = e.target,
728                                                 type = elem.type;
729
730                                         if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
731                                                 e.liveFired = undefined;
732                                                 return trigger( "submit", this, arguments );
733                                         }
734                                 });
735
736                                 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
737                                         var elem = e.target,
738                                                 type = elem.type;
739
740                                         if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
741                                                 e.liveFired = undefined;
742                                                 return trigger( "submit", this, arguments );
743                                         }
744                                 });
745
746                         } else {
747                                 return false;
748                         }
749                 },
750
751                 teardown: function( namespaces ) {
752                         jQuery.event.remove( this, ".specialSubmit" );
753                 }
754         };
755
756 }
757
758 // change delegation, happens here so we have bind.
759 if ( !jQuery.support.changeBubbles ) {
760
761         var changeFilters,
762
763         getVal = function( elem ) {
764                 var type = elem.type, val = elem.value;
765
766                 if ( type === "radio" || type === "checkbox" ) {
767                         val = elem.checked;
768
769                 } else if ( type === "select-multiple" ) {
770                         val = elem.selectedIndex > -1 ?
771                                 jQuery.map( elem.options, function( elem ) {
772                                         return elem.selected;
773                                 }).join("-") :
774                                 "";
775
776                 } else if ( elem.nodeName.toLowerCase() === "select" ) {
777                         val = elem.selectedIndex;
778                 }
779
780                 return val;
781         },
782
783         testChange = function testChange( e ) {
784                 var elem = e.target, data, val;
785
786                 if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
787                         return;
788                 }
789
790                 data = jQuery.data( elem, "_change_data" );
791                 val = getVal(elem);
792
793                 // the current data will be also retrieved by beforeactivate
794                 if ( e.type !== "focusout" || elem.type !== "radio" ) {
795                         jQuery.data( elem, "_change_data", val );
796                 }
797
798                 if ( data === undefined || val === data ) {
799                         return;
800                 }
801
802                 if ( data != null || val ) {
803                         e.type = "change";
804                         e.liveFired = undefined;
805                         return jQuery.event.trigger( e, arguments[1], elem );
806                 }
807         };
808
809         jQuery.event.special.change = {
810                 filters: {
811                         focusout: testChange,
812
813                         beforedeactivate: testChange,
814
815                         click: function( e ) {
816                                 var elem = e.target, type = elem.type;
817
818                                 if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
819                                         return testChange.call( this, e );
820                                 }
821                         },
822
823                         // Change has to be called before submit
824                         // Keydown will be called before keypress, which is used in submit-event delegation
825                         keydown: function( e ) {
826                                 var elem = e.target, type = elem.type;
827
828                                 if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
829                                         (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
830                                         type === "select-multiple" ) {
831                                         return testChange.call( this, e );
832                                 }
833                         },
834
835                         // Beforeactivate happens also before the previous element is blurred
836                         // with this event you can't trigger a change event, but you can store
837                         // information
838                         beforeactivate: function( e ) {
839                                 var elem = e.target;
840                                 jQuery.data( elem, "_change_data", getVal(elem) );
841                         }
842                 },
843
844                 setup: function( data, namespaces ) {
845                         if ( this.type === "file" ) {
846                                 return false;
847                         }
848
849                         for ( var type in changeFilters ) {
850                                 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
851                         }
852
853                         return rformElems.test( this.nodeName );
854                 },
855
856                 teardown: function( namespaces ) {
857                         jQuery.event.remove( this, ".specialChange" );
858
859                         return rformElems.test( this.nodeName );
860                 }
861         };
862
863         changeFilters = jQuery.event.special.change.filters;
864
865         // Handle when the input is .focus()'d
866         changeFilters.focus = changeFilters.beforeactivate;
867 }
868
869 function trigger( type, elem, args ) {
870         args[0].type = type;
871         return jQuery.event.handle.apply( elem, args );
872 }
873
874 // Create "bubbling" focus and blur events
875 if ( document.addEventListener ) {
876         jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
877                 jQuery.event.special[ fix ] = {
878                         setup: function() {
879                                 if ( focusCounts[fix]++ === 0 ) {
880                                         document.addEventListener( orig, handler, true );
881                                 }
882                         },
883                         teardown: function() {
884                                 if ( --focusCounts[fix] === 0 ) {
885                                         document.removeEventListener( orig, handler, true );
886                                 }
887                         }
888                 };
889
890                 function handler( e ) {
891                         e = jQuery.event.fix( e );
892                         e.type = fix;
893                         return jQuery.event.trigger( e, null, e.target );
894                 }
895         });
896 }
897
898 jQuery.each(["bind", "one"], function( i, name ) {
899         jQuery.fn[ name ] = function( type, data, fn ) {
900                 // Handle object literals
901                 if ( typeof type === "object" ) {
902                         for ( var key in type ) {
903                                 this[ name ](key, data, type[key], fn);
904                         }
905                         return this;
906                 }
907
908                 if ( jQuery.isFunction( data ) || data === false ) {
909                         fn = data;
910                         data = undefined;
911                 }
912
913                 var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
914                         jQuery( this ).unbind( event, handler );
915                         return fn.apply( this, arguments );
916                 }) : fn;
917
918                 if ( type === "unload" && name !== "one" ) {
919                         this.one( type, data, fn );
920
921                 } else {
922                         for ( var i = 0, l = this.length; i < l; i++ ) {
923                                 jQuery.event.add( this[i], type, handler, data );
924                         }
925                 }
926
927                 return this;
928         };
929 });
930
931 jQuery.fn.extend({
932         unbind: function( type, fn ) {
933                 // Handle object literals
934                 if ( typeof type === "object" && !type.preventDefault ) {
935                         for ( var key in type ) {
936                                 this.unbind(key, type[key]);
937                         }
938
939                 } else {
940                         for ( var i = 0, l = this.length; i < l; i++ ) {
941                                 jQuery.event.remove( this[i], type, fn );
942                         }
943                 }
944
945                 return this;
946         },
947
948         delegate: function( selector, types, data, fn ) {
949                 return this.live( types, data, fn, selector );
950         },
951
952         undelegate: function( selector, types, fn ) {
953                 if ( arguments.length === 0 ) {
954                                 return this.unbind( "live" );
955
956                 } else {
957                         return this.die( types, null, fn, selector );
958                 }
959         },
960
961         trigger: function( type, data ) {
962                 return this.each(function() {
963                         jQuery.event.trigger( type, data, this );
964                 });
965         },
966
967         triggerHandler: function( type, data ) {
968                 if ( this[0] ) {
969                         var event = jQuery.Event( type );
970                         event.preventDefault();
971                         event.stopPropagation();
972                         jQuery.event.trigger( event, data, this[0] );
973                         return event.result;
974                 }
975         },
976
977         toggle: function( fn ) {
978                 // Save reference to arguments for access in closure
979                 var args = arguments,
980                         i = 1;
981
982                 // link all the functions, so any of them can unbind this click handler
983                 while ( i < args.length ) {
984                         jQuery.proxy( fn, args[ i++ ] );
985                 }
986
987                 return this.click( jQuery.proxy( fn, function( event ) {
988                         // Figure out which function to execute
989                         var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
990                         jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
991
992                         // Make sure that clicks stop
993                         event.preventDefault();
994
995                         // and execute the function
996                         return args[ lastToggle ].apply( this, arguments ) || false;
997                 }));
998         },
999
1000         hover: function( fnOver, fnOut ) {
1001                 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
1002         }
1003 });
1004
1005 var liveMap = {
1006         focus: "focusin",
1007         blur: "focusout",
1008         mouseenter: "mouseover",
1009         mouseleave: "mouseout"
1010 };
1011
1012 jQuery.each(["live", "die"], function( i, name ) {
1013         jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
1014                 var type, i = 0, match, namespaces, preType,
1015                         selector = origSelector || this.selector,
1016                         context = origSelector ? this : jQuery( this.context );
1017
1018                 if ( typeof types === "object" && !types.preventDefault ) {
1019                         for ( var key in types ) {
1020                                 context[ name ]( key, data, types[key], selector );
1021                         }
1022
1023                         return this;
1024                 }
1025
1026                 if ( jQuery.isFunction( data ) ) {
1027                         fn = data;
1028                         data = undefined;
1029                 }
1030
1031                 types = (types || "").split(" ");
1032
1033                 while ( (type = types[ i++ ]) != null ) {
1034                         match = rnamespaces.exec( type );
1035                         namespaces = "";
1036
1037                         if ( match )  {
1038                                 namespaces = match[0];
1039                                 type = type.replace( rnamespaces, "" );
1040                         }
1041
1042                         if ( type === "hover" ) {
1043                                 types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
1044                                 continue;
1045                         }
1046
1047                         preType = type;
1048
1049                         if ( type === "focus" || type === "blur" ) {
1050                                 types.push( liveMap[ type ] + namespaces );
1051                                 type = type + namespaces;
1052
1053                         } else {
1054                                 type = (liveMap[ type ] || type) + namespaces;
1055                         }
1056
1057                         if ( name === "live" ) {
1058                                 // bind live handler
1059                                 for ( var j = 0, l = context.length; j < l; j++ ) {
1060                                         jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
1061                                                 { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
1062                                 }
1063
1064                         } else {
1065                                 // unbind live handler
1066                                 context.unbind( "live." + liveConvert( type, selector ), fn );
1067                         }
1068                 }
1069
1070                 return this;
1071         };
1072 });
1073
1074 function liveHandler( event ) {
1075         var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
1076                 elems = [],
1077                 selectors = [],
1078                 events = jQuery.data( this, this.nodeType ? "events" : "__events__" );
1079
1080         if ( typeof events === "function" ) {
1081                 events = events.events;
1082         }
1083
1084         // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)
1085         if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) {
1086                 return;
1087         }
1088
1089         if ( event.namespace ) {
1090                 namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
1091         }
1092
1093         event.liveFired = this;
1094
1095         var live = events.live.slice(0);
1096
1097         for ( j = 0; j < live.length; j++ ) {
1098                 handleObj = live[j];
1099
1100                 if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
1101                         selectors.push( handleObj.selector );
1102
1103                 } else {
1104                         live.splice( j--, 1 );
1105                 }
1106         }
1107
1108         match = jQuery( event.target ).closest( selectors, event.currentTarget );
1109
1110         for ( i = 0, l = match.length; i < l; i++ ) {
1111                 close = match[i];
1112
1113                 for ( j = 0; j < live.length; j++ ) {
1114                         handleObj = live[j];
1115
1116                         if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) {
1117                                 elem = close.elem;
1118                                 related = null;
1119
1120                                 // Those two events require additional checking
1121                                 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
1122                                         event.type = handleObj.preType;
1123                                         related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
1124                                 }
1125
1126                                 if ( !related || related !== elem ) {
1127                                         elems.push({ elem: elem, handleObj: handleObj, level: close.level });
1128                                 }
1129                         }
1130                 }
1131         }
1132
1133         for ( i = 0, l = elems.length; i < l; i++ ) {
1134                 match = elems[i];
1135
1136                 if ( maxLevel && match.level > maxLevel ) {
1137                         break;
1138                 }
1139
1140                 event.currentTarget = match.elem;
1141                 event.data = match.handleObj.data;
1142                 event.handleObj = match.handleObj;
1143
1144                 ret = match.handleObj.origHandler.apply( match.elem, arguments );
1145
1146                 if ( ret === false || event.isPropagationStopped() ) {
1147                         maxLevel = match.level;
1148
1149                         if ( ret === false ) {
1150                                 stop = false;
1151                         }
1152                         if ( event.isImmediatePropagationStopped() ) {
1153                                 break;
1154                         }
1155                 }
1156         }
1157
1158         return stop;
1159 }
1160
1161 function liveConvert( type, selector ) {
1162         return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
1163 }
1164
1165 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
1166         "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
1167         "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
1168
1169         // Handle event binding
1170         jQuery.fn[ name ] = function( data, fn ) {
1171                 if ( fn == null ) {
1172                         fn = data;
1173                         data = null;
1174                 }
1175
1176                 return arguments.length > 0 ?
1177                         this.bind( name, data, fn ) :
1178                         this.trigger( name );
1179         };
1180
1181         if ( jQuery.attrFn ) {
1182                 jQuery.attrFn[ name ] = true;
1183         }
1184 });
1185
1186 })( jQuery );