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