.unbind() without any arguments now also unbinds namespaced events. fixes #4609 and...
[jquery.git] / src / event.js
index 405e19f..ff6067f 100644 (file)
@@ -13,7 +13,7 @@ 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 )
+               if ( elem.setInterval && ( elem != window && !elem.frameElement ) )
                        elem = window;
 
                // Make sure that the function being executed has a unique ID
                        elem = window;
 
                // Make sure that the function being executed has a unique ID
@@ -56,7 +56,7 @@ jQuery.event = {
 
                        // 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];
-                       
+
                        if ( jQuery.event.specialAll[type] )
                                jQuery.event.specialAll[type].setup.call(elem, data, namespaces);
 
                        if ( jQuery.event.specialAll[type] )
                                jQuery.event.specialAll[type].setup.call(elem, data, namespaces);
 
@@ -116,7 +116,8 @@ jQuery.event = {
                                        // Namespaced event handlers
                                        var namespaces = type.split(".");
                                        type = namespaces.shift();
                                        // Namespaced event handlers
                                        var namespaces = type.split(".");
                                        type = namespaces.shift();
-                                       var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+                                       var all = !namespaces.length,
+                                               namespace = new RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
 
                                        if ( events[type] ) {
                                                // remove the given handler for the given type
 
                                        if ( events[type] ) {
                                                // remove the given handler for the given type
@@ -127,9 +128,9 @@ jQuery.event = {
                                                else
                                                        for ( var handle in events[type] )
                                                                // Handle the removal of namespaced events
                                                else
                                                        for ( var handle in events[type] )
                                                                // Handle the removal of namespaced events
-                                                               if ( namespace.test(events[type][handle].type) )
+                                                               if ( all || namespace.test(events[type][handle].type) )
                                                                        delete events[type][handle];
                                                                        delete events[type][handle];
-                                                                       
+
                                                if ( jQuery.event.specialAll[type] )
                                                        jQuery.event.specialAll[type].teardown.call(elem, namespaces);
 
                                                if ( jQuery.event.specialAll[type] )
                                                        jQuery.event.specialAll[type].teardown.call(elem, namespaces);
 
@@ -196,11 +197,11 @@ jQuery.event = {
                        // don't do events on text and comment nodes
                        if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
                                return undefined;
                        // don't do events on text and comment nodes
                        if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
                                return undefined;
-                       
+
                        // Clean up in case it is reused
                        event.result = undefined;
                        event.target = elem;
                        // Clean up in case it is reused
                        event.result = undefined;
                        event.target = elem;
-                       
+
                        // Clone the incoming data, if any
                        data = jQuery.makeArray(data);
                        data.unshift( event );
                        // Clone the incoming data, if any
                        data = jQuery.makeArray(data);
                        data.unshift( event );
@@ -240,6 +241,7 @@ jQuery.event = {
                var all, handlers;
 
                event = arguments[0] = jQuery.event.fix( event || window.event );
                var all, handlers;
 
                event = arguments[0] = jQuery.event.fix( event || window.event );
+               event.currentTarget = this;
 
                // Namespaced event handlers
                var namespaces = event.type.split(".");
 
                // Namespaced event handlers
                var namespaces = event.type.split(".");
@@ -247,8 +249,8 @@ jQuery.event = {
 
                // Cache this now, all = true means, any handler
                all = !namespaces.length && !event.exclusive;
 
                // Cache this now, all = true means, any handler
                all = !namespaces.length && !event.exclusive;
-               
-               var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+
+               var namespace = new RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
 
                handlers = ( jQuery.data(this, "events") || {} )[event.type];
 
 
                handlers = ( jQuery.data(this, "events") || {} )[event.type];
 
@@ -279,7 +281,7 @@ jQuery.event = {
                }
        },
 
                }
        },
 
-       props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue 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 originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
 
        fix: function(event) {
                if ( event[expando] )
 
        fix: function(event) {
                if ( event[expando] )
@@ -345,7 +347,7 @@ jQuery.event = {
                        teardown: function() {}
                }
        },
                        teardown: function() {}
                }
        },
-       
+
        specialAll: {
                live: {
                        setup: function( selector, namespaces ){
        specialAll: {
                live: {
                        setup: function( selector, namespaces ){
@@ -353,13 +355,13 @@ jQuery.event = {
                        },
                        teardown:  function( namespaces ){
                                if ( namespaces.length ) {
                        },
                        teardown:  function( namespaces ){
                                if ( namespaces.length ) {
-                                       var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
-                                       
+                                       var remove = 0, name = new RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
+
                                        jQuery.each( (jQuery.data(this, "events").live || {}), function(){
                                                if ( name.test(this.type) )
                                                        remove++;
                                        });
                                        jQuery.each( (jQuery.data(this, "events").live || {}), function(){
                                                if ( name.test(this.type) )
                                                        remove++;
                                        });
-                                       
+
                                        if ( remove < 1 )
                                                jQuery.event.remove( this, namespaces[0], liveHandler );
                                }
                                        if ( remove < 1 )
                                                jQuery.event.remove( this, namespaces[0], liveHandler );
                                }
@@ -372,19 +374,19 @@ jQuery.Event = function( src ){
        // Allow instantiation without the 'new' keyword
        if( !this.preventDefault )
                return new jQuery.Event(src);
        // Allow instantiation without the 'new' keyword
        if( !this.preventDefault )
                return new jQuery.Event(src);
-       
+
        // Event object
        if( src && src.type ){
                this.originalEvent = src;
                this.type = src.type;
        // Event object
        if( src && src.type ){
                this.originalEvent = src;
                this.type = src.type;
-               this.timeStamp = src.timeStamp;
        // Event type
        }else
                this.type = src;
 
        // Event type
        }else
                this.type = src;
 
-       if( !this.timeStamp )
-               this.timeStamp = now();
-       
+       // timeStamp is buggy for some events on Firefox(#3843)
+       // So we won't rely on the native value
+       this.timeStamp = now();
+
        // Mark it as fixed
        this[expando] = true;
 };
        // Mark it as fixed
        this[expando] = true;
 };
@@ -440,7 +442,7 @@ var withinElement = function(event) {
        while ( parent && parent != this )
                try { parent = parent.parentNode; }
                catch(e) { parent = this; }
        while ( parent && parent != this )
                try { parent = parent.parentNode; }
                catch(e) { parent = this; }
-       
+
        if( parent != this ){
                // set the correct event type
                event.type = event.data;
        if( parent != this ){
                // set the correct event type
                event.type = event.data;
@@ -448,9 +450,9 @@ var withinElement = function(event) {
                jQuery.event.handle.apply( this, arguments );
        }
 };
                jQuery.event.handle.apply( this, arguments );
        }
 };
-       
-jQuery.each({ 
-       mouseover: 'mouseenter', 
+
+jQuery.each({
+       mouseover: 'mouseenter',
        mouseout: 'mouseleave'
 }, function( orig, fix ){
        jQuery.event.special[ fix ] = {
        mouseout: 'mouseleave'
 }, function( orig, fix ){
        jQuery.event.special[ fix ] = {
@@ -460,7 +462,7 @@ jQuery.each({
                teardown: function(){
                        jQuery.event.remove( this, orig, withinElement );
                }
                teardown: function(){
                        jQuery.event.remove( this, orig, withinElement );
                }
-       };                         
+       };
 });
 
 jQuery.fn.extend({
 });
 
 jQuery.fn.extend({
@@ -499,7 +501,7 @@ jQuery.fn.extend({
                        event.stopPropagation();
                        jQuery.event.trigger( event, data, this[0] );
                        return event.result;
                        event.stopPropagation();
                        jQuery.event.trigger( event, data, this[0] );
                        return event.result;
-               }               
+               }
        },
 
        toggle: function( fn ) {
        },
 
        toggle: function( fn ) {
@@ -542,33 +544,45 @@ jQuery.fn.extend({
 
                return this;
        },
 
                return this;
        },
-       
+
        live: function( type, fn ){
                var proxy = jQuery.event.proxy( fn );
        live: function( type, fn ){
                var proxy = jQuery.event.proxy( fn );
-               proxy.guid += this.selector;
+               proxy.guid += this.selector + type;
 
 
-               jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );
+               jQuery( this.context ).bind( liveConvert(type, this.selector), this.selector, proxy );
 
                return this;
        },
 
                return this;
        },
-       
+
        die: function( type, fn ){
        die: function( type, fn ){
-               jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector } : null );
+               jQuery( this.context ).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
                return this;
        }
 });
 
 function liveHandler( event ){
                return this;
        }
 });
 
 function liveHandler( event ){
-       var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
-               stop = true;
+       var check = new RegExp("(^|\\.)" + event.type + "(\\.|$)"),
+               stop = true,
+               elems = [];
 
        jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
 
        jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
-               if ( !event.isImmediatePropagationStopped() && check.test(fn.type) ) {
+               if ( check.test(fn.type) ) {
                        var elem = jQuery(event.target).closest(fn.data)[0];
                        var elem = jQuery(event.target).closest(fn.data)[0];
-                       if ( elem && fn.call(elem, event, fn.data) === false )
-                               stop = false;
+                       if ( elem )
+                               elems.push({ elem: elem, fn: fn });
                }
        });
                }
        });
+
+       elems.sort(function(a,b) {
+               return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest");
+       });
+
+       jQuery.each(elems, function(){
+               event.currentTarget = this.elem;
+               if ( this.fn.call(this.elem, event, this.fn.data) === false )
+                       return (stop = false);
+       });
+
        return stop;
 }
 
        return stop;
 }
 
@@ -630,7 +644,7 @@ function bindReady(){
 
                // If IE and not an iframe
                // continually check to see if the document is ready
 
                // If IE and not an iframe
                // continually check to see if the document is ready
-               if ( document.documentElement.doScroll && !window.frameElement ) (function(){
+               if ( document.documentElement.doScroll && window == window.top ) (function(){
                        if ( jQuery.isReady ) return;
 
                        try {
                        if ( jQuery.isReady ) return;
 
                        try {
@@ -664,9 +678,12 @@ jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
 // Prevent memory leaks in IE
 // And prevent errors on refresh with events like mouseover in other browsers
 // Window isn't included so as not to unbind existing unload events
 // Prevent memory leaks in IE
 // And prevent errors on refresh with events like mouseover in other browsers
 // Window isn't included so as not to unbind existing unload events
-jQuery( window ).bind( 'unload', function(){ 
+// More info:
+//  - http://isaacschlueter.com/2006/10/msie-memory-leaks/
+//  - https://bugzilla.mozilla.org/show_bug.cgi?id=252542
+jQuery( window ).bind( 'unload', function(){
        for ( var id in jQuery.cache )
                // Skip the window
                if ( id != 1 && jQuery.cache[ id ].handle )
                        jQuery.event.remove( jQuery.cache[ id ].handle.elem );
        for ( var id in jQuery.cache )
                // Skip the window
                if ( id != 1 && jQuery.cache[ id ].handle )
                        jQuery.event.remove( jQuery.cache[ id ].handle.elem );
-}); 
+});