Moved unload abort code so that the event is only bound if the xhr transport is used...
[jquery.git] / src / event.js
index 6e65438..675e5ff 100644 (file)
@@ -1,9 +1,14 @@
+(function( jQuery ) {
+
 var rnamespaces = /\.(.*)$/,
 var rnamespaces = /\.(.*)$/,
+       rformElems = /^(?:textarea|input|select)$/i,
+       rperiod = /\./g,
+       rspace = / /g,
+       rescape = /[^\w\s.|`]/g,
        fcleanup = function( nm ) {
        fcleanup = function( nm ) {
-               return nm.replace(/[^\w\s\.\|`]/g, function( ch ) {
-                       return "\\" + ch;
-               });
-       };
+               return nm.replace(rescape, "\\$&");
+       },
+       focusCounts = { focusin: 0, focusout: 0 };
 
 /*
  * A number of helper functions used for managing events.
 
 /*
  * A number of helper functions used for managing events.
@@ -21,10 +26,17 @@ jQuery.event = {
 
                // For whatever reason, IE has trouble passing the window object
                // around, causing it to be cloned in the process
 
                // For whatever reason, IE has trouble passing the window object
                // around, causing it to be cloned in the process
-               if ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) {
+               if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) {
                        elem = window;
                }
 
                        elem = window;
                }
 
+               if ( handler === false ) {
+                       handler = returnFalse;
+               } else if ( !handler ) {
+                       // Fixes bug #7229. Fix recommended by jdalton
+                 return;
+               }
+
                var handleObjIn, handleObj;
 
                if ( handler.handler ) {
                var handleObjIn, handleObj;
 
                if ( handler.handler ) {
@@ -46,8 +58,28 @@ jQuery.event = {
                        return;
                }
 
                        return;
                }
 
-               var events = elemData.events = elemData.events || {},
-                       eventHandle = elemData.handle, eventHandle;
+               // Use a key less likely to result in collisions for plain JS objects.
+               // Fixes bug #7150.
+               var eventKey = elem.nodeType ? "events" : "__events__",
+                       events = elemData[ eventKey ],
+                       eventHandle = elemData.handle;
+
+               if ( typeof events === "function" ) {
+                       // On plain objects events is a fn that holds the the data
+                       // which prevents this data from being JSON serialized
+                       // the function does not need to be called, it just contains the data
+                       eventHandle = events.handle;
+                       events = events.events;
+
+               } else if ( !events ) {
+                       if ( !elem.nodeType ) {
+                               // On plain objects, create a fn that acts as the holder
+                               // of the values to avoid JSON serialization of event data
+                               elemData[ eventKey ] = elemData = function(){};
+                       }
+
+                       elemData.events = events = {};
+               }
 
                if ( !eventHandle ) {
                        elemData.handle = eventHandle = function() {
 
                if ( !eventHandle ) {
                        elemData.handle = eventHandle = function() {
@@ -86,7 +118,9 @@ jQuery.event = {
                        }
 
                        handleObj.type = type;
                        }
 
                        handleObj.type = type;
-                       handleObj.guid = handler.guid;
+                       if ( !handleObj.guid ) {
+                               handleObj.guid = handler.guid;
+                       }
 
                        // Get the current list of functions bound to this event
                        var handlers = events[ type ],
 
                        // Get the current list of functions bound to this event
                        var handlers = events[ type ],
@@ -109,9 +143,13 @@ jQuery.event = {
                                        }
                                }
                        }
                                        }
                                }
                        }
-                       
-                       if ( special.add ) { 
-                               special.add.call( elem, handleObj ); 
+
+                       if ( special.add ) {
+                               special.add.call( elem, handleObj );
+
+                               if ( !handleObj.handler.guid ) {
+                                       handleObj.handler.guid = handler.guid;
+                               }
                        }
 
                        // Add the function to the element's handler list
                        }
 
                        // Add the function to the element's handler list
@@ -134,14 +172,24 @@ jQuery.event = {
                        return;
                }
 
                        return;
                }
 
-               var ret, type, fn, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
+               if ( handler === false ) {
+                       handler = returnFalse;
+               }
+
+               var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
+                       eventKey = elem.nodeType ? "events" : "__events__",
                        elemData = jQuery.data( elem ),
                        elemData = jQuery.data( elem ),
-                       events = elemData && elemData.events;
+                       events = elemData && elemData[ eventKey ];
 
                if ( !elemData || !events ) {
                        return;
                }
 
 
                if ( !elemData || !events ) {
                        return;
                }
 
+               if ( typeof events === "function" ) {
+                       elemData = events;
+                       events = events.events;
+               }
+
                // types is actually an event object here
                if ( types && types.type ) {
                        handler = types.handler;
                // types is actually an event object here
                if ( types && types.type ) {
                        handler = types.handler;
@@ -174,8 +222,8 @@ jQuery.event = {
                                namespaces = type.split(".");
                                type = namespaces.shift();
 
                                namespaces = type.split(".");
                                type = namespaces.shift();
 
-                               namespace = new RegExp("(^|\\.)" + 
-                                       jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)")
+                               namespace = new RegExp("(^|\\.)" +
+                                       jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
                        }
 
                        eventType = events[ type ];
                        }
 
                        eventType = events[ type ];
@@ -185,7 +233,7 @@ jQuery.event = {
                        }
 
                        if ( !handler ) {
                        }
 
                        if ( !handler ) {
-                               for ( var j = 0; j < eventType.length; j++ ) {
+                               for ( j = 0; j < eventType.length; j++ ) {
                                        handleObj = eventType[ j ];
 
                                        if ( all || namespace.test( handleObj.namespace ) ) {
                                        handleObj = eventType[ j ];
 
                                        if ( all || namespace.test( handleObj.namespace ) ) {
@@ -199,7 +247,7 @@ jQuery.event = {
 
                        special = jQuery.event.special[ type ] || {};
 
 
                        special = jQuery.event.special[ type ] || {};
 
-                       for ( var j = pos || 0; j < eventType.length; j++ ) {
+                       for ( j = pos || 0; j < eventType.length; j++ ) {
                                handleObj = eventType[ j ];
 
                                if ( handler.guid === handleObj.guid ) {
                                handleObj = eventType[ j ];
 
                                if ( handler.guid === handleObj.guid ) {
@@ -223,7 +271,7 @@ jQuery.event = {
                        // remove generic event handler if no more handlers exist
                        if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
                                if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
                        // remove generic event handler if no more handlers exist
                        if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
                                if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
-                                       removeEvent( elem, type, elemData.handle );
+                                       jQuery.removeEvent( elem, type, elemData.handle );
                                }
 
                                ret = null;
                                }
 
                                ret = null;
@@ -241,7 +289,10 @@ jQuery.event = {
                        delete elemData.events;
                        delete elemData.handle;
 
                        delete elemData.events;
                        delete elemData.handle;
 
-                       if ( jQuery.isEmptyObject( elemData ) ) {
+                       if ( typeof elemData === "function" ) {
+                               jQuery.removeData( elem, eventKey );
+
+                       } else if ( jQuery.isEmptyObject( elemData ) ) {
                                jQuery.removeData( elem );
                        }
                }
                                jQuery.removeData( elem );
                        }
                }
@@ -256,7 +307,7 @@ jQuery.event = {
                if ( !bubbling ) {
                        event = typeof event === "object" ?
                                // jQuery.Event object
                if ( !bubbling ) {
                        event = typeof event === "object" ?
                                // jQuery.Event object
-                               event[expando] ? event :
+                               event[ jQuery.expando ] ? event :
                                // Object literal
                                jQuery.extend( jQuery.Event(type), event ) :
                                // Just the event type (string)
                                // Object literal
                                jQuery.extend( jQuery.Event(type), event ) :
                                // Just the event type (string)
@@ -301,7 +352,10 @@ jQuery.event = {
                event.currentTarget = elem;
 
                // Trigger the event, it is assumed that "handle" is a function
                event.currentTarget = elem;
 
                // Trigger the event, it is assumed that "handle" is a function
-               var handle = jQuery.data( elem, "handle" );
+               var handle = elem.nodeType ?
+                       jQuery.data( elem, "handle" ) :
+                       (jQuery.data( elem, "__events__" ) || {}).handle;
+
                if ( handle ) {
                        handle.apply( elem, data );
                }
                if ( handle ) {
                        handle.apply( elem, data );
                }
@@ -313,41 +367,44 @@ jQuery.event = {
                        if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
                                if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
                                        event.result = false;
                        if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
                                if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
                                        event.result = false;
+                                       event.preventDefault();
                                }
                        }
 
                // prevent IE from throwing an error for some elements with some event types, see #3533
                                }
                        }
 
                // prevent IE from throwing an error for some elements with some event types, see #3533
-               } catch (e) {}
+               } catch (inlineError) {}
 
                if ( !event.isPropagationStopped() && parent ) {
                        jQuery.event.trigger( event, data, parent, true );
 
                } else if ( !event.isDefaultPrevented() ) {
 
                if ( !event.isPropagationStopped() && parent ) {
                        jQuery.event.trigger( event, data, parent, true );
 
                } else if ( !event.isDefaultPrevented() ) {
-                       var target = event.target, old,
-                               isClick = jQuery.nodeName(target, "a") && type === "click",
-                               special = jQuery.event.special[ type ] || {};
+                       var old,
+                               target = event.target,
+                               targetType = type.replace( rnamespaces, "" ),
+                               isClick = jQuery.nodeName( target, "a" ) && targetType === "click",
+                               special = jQuery.event.special[ targetType ] || {};
 
 
-                       if ( (!special._default || special._default.call( elem, event ) === false) && 
+                       if ( (!special._default || special._default.call( elem, event ) === false) &&
                                !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
 
                                try {
                                !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
 
                                try {
-                                       if ( target[ type ] ) {
+                                       if ( target[ targetType ] ) {
                                                // Make sure that we don't accidentally re-trigger the onFOO events
                                                // Make sure that we don't accidentally re-trigger the onFOO events
-                                               old = target[ "on" + type ];
+                                               old = target[ "on" + targetType ];
 
                                                if ( old ) {
 
                                                if ( old ) {
-                                                       target[ "on" + type ] = null;
+                                                       target[ "on" + targetType ] = null;
                                                }
 
                                                jQuery.event.triggered = true;
                                                }
 
                                                jQuery.event.triggered = true;
-                                               target[ type ]();
+                                               target[ targetType ]();
                                        }
 
                                // prevent IE from throwing an error for some elements with some event types, see #3533
                                        }
 
                                // prevent IE from throwing an error for some elements with some event types, see #3533
-                               } catch (e) {}
+                               } catch (triggerError) {}
 
                                if ( old ) {
 
                                if ( old ) {
-                                       target[ "on" + type ] = old;
+                                       target[ "on" + targetType ] = old;
                                }
 
                                jQuery.event.triggered = false;
                                }
 
                                jQuery.event.triggered = false;
@@ -356,9 +413,11 @@ jQuery.event = {
        },
 
        handle: function( event ) {
        },
 
        handle: function( event ) {
-               var all, handlers, namespaces, namespace, events;
+               var all, handlers, namespaces, namespace_re, events,
+                       namespace_sort = [],
+                       args = jQuery.makeArray( arguments );
 
 
-               event = arguments[0] = jQuery.event.fix( event || window.event );
+               event = args[0] = jQuery.event.fix( event || window.event );
                event.currentTarget = this;
 
                // Namespaced event handlers
                event.currentTarget = this;
 
                // Namespaced event handlers
@@ -367,10 +426,19 @@ jQuery.event = {
                if ( !all ) {
                        namespaces = event.type.split(".");
                        event.type = namespaces.shift();
                if ( !all ) {
                        namespaces = event.type.split(".");
                        event.type = namespaces.shift();
-                       namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)");
+                       namespace_sort = namespaces.slice(0).sort();
+                       namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
                }
 
                }
 
-               var events = jQuery.data(this, "events"), handlers = events[ event.type ];
+               event.namespace = event.namespace || namespace_sort.join(".");
+
+               events = jQuery.data(this, this.nodeType ? "events" : "__events__");
+
+               if ( typeof events === "function" ) {
+                       events = events.events;
+               }
+
+               handlers = (events || {})[ event.type ];
 
                if ( events && handlers ) {
                        // Clone the handlers to prevent manipulation
 
                if ( events && handlers ) {
                        // Clone the handlers to prevent manipulation
@@ -380,14 +448,14 @@ jQuery.event = {
                                var handleObj = handlers[ j ];
 
                                // Filter the functions by class
                                var handleObj = handlers[ j ];
 
                                // Filter the functions by class
-                               if ( all || namespace.test( handleObj.namespace ) ) {
+                               if ( all || namespace_re.test( handleObj.namespace ) ) {
                                        // Pass in a reference to the handler function itself
                                        // So that we can later remove it
                                        event.handler = handleObj.handler;
                                        event.data = handleObj.data;
                                        event.handleObj = handleObj;
                                        // Pass in a reference to the handler function itself
                                        // So that we can later remove it
                                        event.handler = handleObj.handler;
                                        event.data = handleObj.data;
                                        event.handleObj = handleObj;
-       
-                                       var ret = handleObj.handler.apply( this, arguments );
+
+                                       var ret = handleObj.handler.apply( this, args );
 
                                        if ( ret !== undefined ) {
                                                event.result = ret;
 
                                        if ( ret !== undefined ) {
                                                event.result = ret;
@@ -407,10 +475,10 @@ jQuery.event = {
                return event.result;
        },
 
                return event.result;
        },
 
-       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(" "),
+       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(" "),
 
        fix: function( event ) {
 
        fix: function( event ) {
-               if ( event[ expando ] ) {
+               if ( event[ jQuery.expando ] ) {
                        return event;
                }
 
                        return event;
                }
 
@@ -426,7 +494,8 @@ jQuery.event = {
 
                // Fix target property, if necessary
                if ( !event.target ) {
 
                // Fix target property, if necessary
                if ( !event.target ) {
-                       event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
+                       // Fixes #1925 where srcElement might not be defined either
+                       event.target = event.srcElement || document;
                }
 
                // check if target is a textnode (safari)
                }
 
                // check if target is a textnode (safari)
@@ -441,14 +510,16 @@ jQuery.event = {
 
                // Calculate pageX/Y if missing and clientX/Y available
                if ( event.pageX == null && event.clientX != null ) {
 
                // Calculate pageX/Y if missing and clientX/Y available
                if ( event.pageX == null && event.clientX != null ) {
-                       var doc = document.documentElement, body = document.body;
+                       var doc = document.documentElement,
+                               body = document.body;
+
                        event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
                        event.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);
                }
 
                // Add which for key events
                        event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
                        event.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);
                }
 
                // Add which for key events
-               if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) {
-                       event.which = event.charCode || event.keyCode;
+               if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
+                       event.which = event.charCode != null ? event.charCode : event.keyCode;
                }
 
                // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
                }
 
                // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
@@ -480,36 +551,24 @@ jQuery.event = {
 
                live: {
                        add: function( handleObj ) {
 
                live: {
                        add: function( handleObj ) {
-                               jQuery.event.add( this, handleObj.origType, jQuery.extend({}, handleObj, {handler: liveHandler}) ); 
+                               jQuery.event.add( this,
+                                       liveConvert( handleObj.origType, handleObj.selector ),
+                                       jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
                        },
 
                        remove: function( handleObj ) {
                        },
 
                        remove: function( handleObj ) {
-                               var remove = true,
-                                       type = handleObj.origType.replace(rnamespaces, "");
-                               
-                               jQuery.each( jQuery.data(this, "events").live || [], function() {
-                                       if ( type === this.origType.replace(rnamespaces, "") ) {
-                                               remove = false;
-                                               return false;
-                                       }
-                               });
-
-                               if ( remove ) {
-                                       jQuery.event.remove( this, handleObj.origType, liveHandler );
-                               }
+                               jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
                        }
                        }
-
                },
 
                beforeunload: {
                        setup: function( data, namespaces, eventHandle ) {
                                // We only want to do this special case on windows
                },
 
                beforeunload: {
                        setup: function( data, namespaces, eventHandle ) {
                                // We only want to do this special case on windows
-                               if ( this.setInterval ) {
+                               if ( jQuery.isWindow( this ) ) {
                                        this.onbeforeunload = eventHandle;
                                }
                                        this.onbeforeunload = eventHandle;
                                }
-
-                               return false;
                        },
                        },
+
                        teardown: function( namespaces, eventHandle ) {
                                if ( this.onbeforeunload === eventHandle ) {
                                        this.onbeforeunload = null;
                        teardown: function( namespaces, eventHandle ) {
                                if ( this.onbeforeunload === eventHandle ) {
                                        this.onbeforeunload = null;
@@ -519,12 +578,16 @@ jQuery.event = {
        }
 };
 
        }
 };
 
-var removeEvent = document.removeEventListener ?
+jQuery.removeEvent = document.removeEventListener ?
        function( elem, type, handle ) {
        function( elem, type, handle ) {
-               elem.removeEventListener( type, handle, false );
-       } : 
+               if ( elem.removeEventListener ) {
+                       elem.removeEventListener( type, handle, false );
+               }
+       } :
        function( elem, type, handle ) {
        function( elem, type, handle ) {
-               elem.detachEvent( "on" + type, handle );
+               if ( elem.detachEvent ) {
+                       elem.detachEvent( "on" + type, handle );
+               }
        };
 
 jQuery.Event = function( src ) {
        };
 
 jQuery.Event = function( src ) {
@@ -537,6 +600,12 @@ jQuery.Event = function( src ) {
        if ( src && src.type ) {
                this.originalEvent = src;
                this.type = src.type;
        if ( src && src.type ) {
                this.originalEvent = src;
                this.type = src.type;
+
+               // Events bubbling up the document may have been marked as prevented
+               // by a handler lower down the tree; reflect the correct value.
+               this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
+                       src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
+
        // Event type
        } else {
                this.type = src;
        // Event type
        } else {
                this.type = src;
@@ -544,10 +613,10 @@ jQuery.Event = function( src ) {
 
        // timeStamp is buggy for some events on Firefox(#3843)
        // So we won't rely on the native value
 
        // timeStamp is buggy for some events on Firefox(#3843)
        // So we won't rely on the native value
-       this.timeStamp = now();
+       this.timeStamp = jQuery.now();
 
        // Mark it as fixed
 
        // Mark it as fixed
-       this[ expando ] = true;
+       this[ jQuery.expando ] = true;
 };
 
 function returnFalse() {
 };
 
 function returnFalse() {
@@ -567,13 +636,15 @@ jQuery.Event.prototype = {
                if ( !e ) {
                        return;
                }
                if ( !e ) {
                        return;
                }
-               
+
                // if preventDefault exists run it on the original event
                if ( e.preventDefault ) {
                        e.preventDefault();
                // if preventDefault exists run it on the original event
                if ( e.preventDefault ) {
                        e.preventDefault();
-               }
+
                // otherwise set the returnValue property of the original event to false (IE)
                // otherwise set the returnValue property of the original event to false (IE)
-               e.returnValue = false;
+               } else {
+                       e.returnValue = false;
+               }
        },
        stopPropagation: function() {
                this.isPropagationStopped = returnTrue;
        },
        stopPropagation: function() {
                this.isPropagationStopped = returnTrue;
@@ -651,19 +722,23 @@ if ( !jQuery.support.submitBubbles ) {
 
        jQuery.event.special.submit = {
                setup: function( data, namespaces ) {
 
        jQuery.event.special.submit = {
                setup: function( data, namespaces ) {
-                       if ( this.nodeName.toLowerCase() !== "form" ) {
+                       if ( this.nodeName && this.nodeName.toLowerCase() !== "form" ) {
                                jQuery.event.add(this, "click.specialSubmit", function( e ) {
                                jQuery.event.add(this, "click.specialSubmit", function( e ) {
-                                       var elem = e.target, type = elem.type;
+                                       var elem = e.target,
+                                               type = elem.type;
 
                                        if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
 
                                        if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
+                                               e.liveFired = undefined;
                                                return trigger( "submit", this, arguments );
                                        }
                                });
                                                return trigger( "submit", this, arguments );
                                        }
                                });
-        
+
                                jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
                                jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
-                                       var elem = e.target, type = elem.type;
+                                       var elem = e.target,
+                                               type = elem.type;
 
                                        if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
 
                                        if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
+                                               e.liveFired = undefined;
                                                return trigger( "submit", this, arguments );
                                        }
                                });
                                                return trigger( "submit", this, arguments );
                                        }
                                });
@@ -683,9 +758,7 @@ if ( !jQuery.support.submitBubbles ) {
 // change delegation, happens here so we have bind.
 if ( !jQuery.support.changeBubbles ) {
 
 // change delegation, happens here so we have bind.
 if ( !jQuery.support.changeBubbles ) {
 
-       var formElems = /textarea|input|select/i,
-
-       changeFilters,
+       var changeFilters,
 
        getVal = function( elem ) {
                var type = elem.type, val = elem.value;
 
        getVal = function( elem ) {
                var type = elem.type, val = elem.value;
@@ -710,7 +783,7 @@ if ( !jQuery.support.changeBubbles ) {
        testChange = function testChange( e ) {
                var elem = e.target, data, val;
 
        testChange = function testChange( e ) {
                var elem = e.target, data, val;
 
-               if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
+               if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
                        return;
                }
 
                        return;
                }
 
@@ -721,20 +794,23 @@ if ( !jQuery.support.changeBubbles ) {
                if ( e.type !== "focusout" || elem.type !== "radio" ) {
                        jQuery.data( elem, "_change_data", val );
                }
                if ( e.type !== "focusout" || elem.type !== "radio" ) {
                        jQuery.data( elem, "_change_data", val );
                }
-               
+
                if ( data === undefined || val === data ) {
                        return;
                }
 
                if ( data != null || val ) {
                        e.type = "change";
                if ( data === undefined || val === data ) {
                        return;
                }
 
                if ( data != null || val ) {
                        e.type = "change";
+                       e.liveFired = undefined;
                        return jQuery.event.trigger( e, arguments[1], elem );
                }
        };
 
        jQuery.event.special.change = {
                filters: {
                        return jQuery.event.trigger( e, arguments[1], elem );
                }
        };
 
        jQuery.event.special.change = {
                filters: {
-                       focusout: testChange, 
+                       focusout: testChange,
+
+                       beforedeactivate: testChange,
 
                        click: function( e ) {
                                var elem = e.target, type = elem.type;
 
                        click: function( e ) {
                                var elem = e.target, type = elem.type;
@@ -758,7 +834,7 @@ if ( !jQuery.support.changeBubbles ) {
 
                        // Beforeactivate happens also before the previous element is blurred
                        // with this event you can't trigger a change event, but you can store
 
                        // Beforeactivate happens also before the previous element is blurred
                        // with this event you can't trigger a change event, but you can store
-                       // information/focus[in] is not needed anymore
+                       // information
                        beforeactivate: function( e ) {
                                var elem = e.target;
                                jQuery.data( elem, "_change_data", getVal(elem) );
                        beforeactivate: function( e ) {
                                var elem = e.target;
                                jQuery.data( elem, "_change_data", getVal(elem) );
@@ -774,17 +850,20 @@ if ( !jQuery.support.changeBubbles ) {
                                jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
                        }
 
                                jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
                        }
 
-                       return formElems.test( this.nodeName );
+                       return rformElems.test( this.nodeName );
                },
 
                teardown: function( namespaces ) {
                        jQuery.event.remove( this, ".specialChange" );
 
                },
 
                teardown: function( namespaces ) {
                        jQuery.event.remove( this, ".specialChange" );
 
-                       return formElems.test( this.nodeName );
+                       return rformElems.test( this.nodeName );
                }
        };
 
        changeFilters = jQuery.event.special.change.filters;
                }
        };
 
        changeFilters = jQuery.event.special.change.filters;
+
+       // Handle when the input is .focus()'d
+       changeFilters.focus = changeFilters.beforeactivate;
 }
 
 function trigger( type, elem, args ) {
 }
 
 function trigger( type, elem, args ) {
@@ -797,17 +876,21 @@ if ( document.addEventListener ) {
        jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
                jQuery.event.special[ fix ] = {
                        setup: function() {
        jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
                jQuery.event.special[ fix ] = {
                        setup: function() {
-                               this.addEventListener( orig, handler, true );
-                       }, 
-                       teardown: function() { 
-                               this.removeEventListener( orig, handler, true );
+                               if ( focusCounts[fix]++ === 0 ) {
+                                       document.addEventListener( orig, handler, true );
+                               }
+                       },
+                       teardown: function() {
+                               if ( --focusCounts[fix] === 0 ) {
+                                       document.removeEventListener( orig, handler, true );
+                               }
                        }
                };
 
                        }
                };
 
-               function handler( e ) { 
+               function handler( e ) {
                        e = jQuery.event.fix( e );
                        e.type = fix;
                        e = jQuery.event.fix( e );
                        e.type = fix;
-                       return jQuery.event.handle.call( this, e );
+                       return jQuery.event.trigger( e, null, e.target );
                }
        });
 }
                }
        });
 }
@@ -821,8 +904,8 @@ jQuery.each(["bind", "one"], function( i, name ) {
                        }
                        return this;
                }
                        }
                        return this;
                }
-               
-               if ( jQuery.isFunction( data ) ) {
+
+               if ( jQuery.isFunction( data ) || data === false ) {
                        fn = data;
                        data = undefined;
                }
                        fn = data;
                        data = undefined;
                }
@@ -861,20 +944,20 @@ jQuery.fn.extend({
 
                return this;
        },
 
                return this;
        },
-       
+
        delegate: function( selector, types, data, fn ) {
                return this.live( types, data, fn, selector );
        },
        delegate: function( selector, types, data, fn ) {
                return this.live( types, data, fn, selector );
        },
-       
+
        undelegate: function( selector, types, fn ) {
                if ( arguments.length === 0 ) {
                                return this.unbind( "live" );
        undelegate: function( selector, types, fn ) {
                if ( arguments.length === 0 ) {
                                return this.unbind( "live" );
-               
+
                } else {
                        return this.die( types, null, fn, selector );
                }
        },
                } else {
                        return this.die( types, null, fn, selector );
                }
        },
-       
+
        trigger: function( type, data ) {
                return this.each(function() {
                        jQuery.event.trigger( type, data, this );
        trigger: function( type, data ) {
                return this.each(function() {
                        jQuery.event.trigger( type, data, this );
@@ -893,7 +976,8 @@ jQuery.fn.extend({
 
        toggle: function( fn ) {
                // Save reference to arguments for access in closure
 
        toggle: function( fn ) {
                // Save reference to arguments for access in closure
-               var args = arguments, i = 1;
+               var args = arguments,
+                       i = 1;
 
                // link all the functions, so any of them can unbind this click handler
                while ( i < args.length ) {
 
                // link all the functions, so any of them can unbind this click handler
                while ( i < args.length ) {
@@ -931,6 +1015,14 @@ jQuery.each(["live", "die"], function( i, name ) {
                        selector = origSelector || this.selector,
                        context = origSelector ? this : jQuery( this.context );
 
                        selector = origSelector || this.selector,
                        context = origSelector ? this : jQuery( this.context );
 
+               if ( typeof types === "object" && !types.preventDefault ) {
+                       for ( var key in types ) {
+                               context[ name ]( key, data, types[key], selector );
+                       }
+
+                       return this;
+               }
+
                if ( jQuery.isFunction( data ) ) {
                        fn = data;
                        data = undefined;
                if ( jQuery.isFunction( data ) ) {
                        fn = data;
                        data = undefined;
@@ -964,31 +1056,40 @@ jQuery.each(["live", "die"], function( i, name ) {
 
                        if ( name === "live" ) {
                                // bind live handler
 
                        if ( name === "live" ) {
                                // bind live handler
-                               context.each(function(){
-                                       jQuery.event.add( this, liveConvert( type, selector ),
+                               for ( var j = 0, l = context.length; j < l; j++ ) {
+                                       jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
                                                { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
                                                { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
-                               });
+                               }
 
                        } else {
                                // unbind live handler
 
                        } else {
                                // unbind live handler
-                               context.unbind( liveConvert( type, selector ), fn );
+                               context.unbind( "live." + liveConvert( type, selector ), fn );
                        }
                }
                        }
                }
-               
+
                return this;
                return this;
-       }
+       };
 });
 
 function liveHandler( event ) {
 });
 
 function liveHandler( event ) {
-       var stop, elems = [], selectors = [], args = arguments,
-               related, match, handleObj, elem, j, i, l, data,
-               events = jQuery.data( this, "events" );
+       var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
+               elems = [],
+               selectors = [],
+               events = jQuery.data( this, this.nodeType ? "events" : "__events__" );
 
 
-       // Make sure we avoid non-left-click bubbling in Firefox (#3861)
-       if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {
+       if ( typeof events === "function" ) {
+               events = events.events;
+       }
+
+       // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)
+       if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) {
                return;
        }
 
                return;
        }
 
+       if ( event.namespace ) {
+               namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
+       }
+
        event.liveFired = this;
 
        var live = events.live.slice(0);
        event.liveFired = this;
 
        var live = events.live.slice(0);
@@ -1007,20 +1108,23 @@ function liveHandler( event ) {
        match = jQuery( event.target ).closest( selectors, event.currentTarget );
 
        for ( i = 0, l = match.length; i < l; i++ ) {
        match = jQuery( event.target ).closest( selectors, event.currentTarget );
 
        for ( i = 0, l = match.length; i < l; i++ ) {
+               close = match[i];
+
                for ( j = 0; j < live.length; j++ ) {
                        handleObj = live[j];
 
                for ( j = 0; j < live.length; j++ ) {
                        handleObj = live[j];
 
-                       if ( match[i].selector === handleObj.selector ) {
-                               elem = match[i].elem;
+                       if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) {
+                               elem = close.elem;
                                related = null;
 
                                // Those two events require additional checking
                                if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
                                related = null;
 
                                // Those two events require additional checking
                                if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
+                                       event.type = handleObj.preType;
                                        related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
                                }
 
                                if ( !related || related !== elem ) {
                                        related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
                                }
 
                                if ( !related || related !== elem ) {
-                                       elems.push({ elem: elem, handleObj: handleObj });
+                                       elems.push({ elem: elem, handleObj: handleObj, level: close.level });
                                }
                        }
                }
                                }
                        }
                }
@@ -1028,13 +1132,26 @@ function liveHandler( event ) {
 
        for ( i = 0, l = elems.length; i < l; i++ ) {
                match = elems[i];
 
        for ( i = 0, l = elems.length; i < l; i++ ) {
                match = elems[i];
+
+               if ( maxLevel && match.level > maxLevel ) {
+                       break;
+               }
+
                event.currentTarget = match.elem;
                event.data = match.handleObj.data;
                event.handleObj = match.handleObj;
 
                event.currentTarget = match.elem;
                event.data = match.handleObj.data;
                event.handleObj = match.handleObj;
 
-               if ( match.handleObj.origHandler.apply( match.elem, args ) === false ) {
-                       stop = false;
-                       break;
+               ret = match.handleObj.origHandler.apply( match.elem, arguments );
+
+               if ( ret === false || event.isPropagationStopped() ) {
+                       maxLevel = match.level;
+
+                       if ( ret === false ) {
+                               stop = false;
+                       }
+                       if ( event.isImmediatePropagationStopped() ) {
+                               break;
+                       }
                }
        }
 
                }
        }
 
@@ -1042,7 +1159,7 @@ function liveHandler( event ) {
 }
 
 function liveConvert( type, selector ) {
 }
 
 function liveConvert( type, selector ) {
-       return "live." + (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&");
+       return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
 }
 
 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
 }
 
 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
@@ -1050,8 +1167,15 @@ jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblcl
        "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
 
        // Handle event binding
        "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
 
        // Handle event binding
-       jQuery.fn[ name ] = function( fn ) {
-               return fn ? this.bind( name, fn ) : this.trigger( name );
+       jQuery.fn[ name ] = function( data, fn ) {
+               if ( fn == null ) {
+                       fn = data;
+                       data = null;
+               }
+
+               return arguments.length > 0 ?
+                       this.bind( name, data, fn ) :
+                       this.trigger( name );
        };
 
        if ( jQuery.attrFn ) {
        };
 
        if ( jQuery.attrFn ) {
@@ -1059,19 +1183,4 @@ jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblcl
        }
 });
 
        }
 });
 
-// Prevent memory leaks in IE
-// Window isn't included so as not to unbind existing unload events
-// More info:
-//  - http://isaacschlueter.com/2006/10/msie-memory-leaks/
-if ( window.attachEvent && !window.addEventListener ) {
-       window.attachEvent("onunload", function() {
-               for ( var id in jQuery.cache ) {
-                       if ( jQuery.cache[ id ].handle ) {
-                               // Try/Catch is to handle iframes being unloaded, see #4280
-                               try {
-                                       jQuery.event.remove( jQuery.cache[ id ].handle.elem );
-                               } catch(e) {}
-                       }
-               }
-       });
-}
+})( jQuery );