remove trailing spaces
[jquery.git] / src / event.js
index c7e2f4f..4a0a412 100644 (file)
@@ -26,10 +26,7 @@ jQuery.event = {
                        var fn = handler;
 
                        // Create unique handler function, wrapped around original handler
-                       handler = this.proxy( fn, function() {
-                               // Pass arguments and context to original handler
-                               return fn.apply(this, arguments);
-                       });
+                       handler = this.proxy( fn );
 
                        // Store data in unique handler
                        handler.data = data;
@@ -59,7 +56,7 @@ jQuery.event = {
 
                        // 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);
 
@@ -119,7 +116,7 @@ jQuery.event = {
                                        // Namespaced event handlers
                                        var namespaces = type.split(".");
                                        type = namespaces.shift();
-                                       var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+                                       var namespace = new RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
 
                                        if ( events[type] ) {
                                                // remove the given handler for the given type
@@ -128,11 +125,11 @@ jQuery.event = {
 
                                                // remove all handlers for the given type
                                                else
-                                                       for ( handler in events[type] )
+                                                       for ( var handle in events[type] )
                                                                // Handle the removal of namespaced events
-                                                               if ( namespace.test(events[type][handler].type) )
-                                                                       delete events[type][handler];
-                                                                       
+                                                               if ( namespace.test(events[type][handle].type) )
+                                                                       delete events[type][handle];
+
                                                if ( jQuery.event.specialAll[type] )
                                                        jQuery.event.specialAll[type].teardown.call(elem, namespaces);
 
@@ -163,7 +160,8 @@ jQuery.event = {
                }
        },
 
-       trigger: function( event, data, elem, bubbling /* internal */ ) {
+       // bubbling is internal
+       trigger: function( event, data, elem, bubbling ) {
                // Event object or event type
                var type = event.type || event;
 
@@ -198,36 +196,29 @@ jQuery.event = {
                        // don't do events on text and comment nodes
                        if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
                                return undefined;
-                       
-                       // AT_TARGET phase (not bubbling)
-                       if( !bubbling ){
-                               // 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 );
-                       }
+
+                       // 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 );
                }
 
                event.currentTarget = elem;
 
-               var fn = jQuery.isFunction( elem[ type ] );
-
                // Trigger the event, it is assumed that "handle" is a function
                var handle = jQuery.data(elem, "handle");
                if ( handle )
                        handle.apply( elem, data );
 
                // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
-               if ( (!fn || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
+               if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
                        event.result = false;
 
-               // data.shift();
-
                // Trigger the native events (except for clicks on links)
-               if ( !bubbling && fn && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
+               if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
                        this.triggered = true;
                        try {
                                elem[ type ]();
@@ -235,13 +226,13 @@ jQuery.event = {
                        } catch (e) {}
                }
 
+               this.triggered = false;
+
                if ( !event.isPropagationStopped() ) {
                        var parent = elem.parentNode || elem.ownerDocument;
                        if ( parent )
                                jQuery.event.trigger(event, data, parent, true);
                }
-
-               this.triggered = false;
        },
 
        handle: function(event) {
@@ -249,6 +240,7 @@ jQuery.event = {
                var all, handlers;
 
                event = arguments[0] = jQuery.event.fix( event || window.event );
+               event.currentTarget = this;
 
                // Namespaced event handlers
                var namespaces = event.type.split(".");
@@ -256,8 +248,8 @@ jQuery.event = {
 
                // 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];
 
@@ -340,6 +332,7 @@ jQuery.event = {
        },
 
        proxy: function( fn, proxy ){
+               proxy = proxy || function(){ return fn.apply(this, arguments); };
                // Set the guid of unique handler to the same of original handler, so it can be removed
                proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
                // So proxy can be declared as an argument
@@ -353,7 +346,7 @@ jQuery.event = {
                        teardown: function() {}
                }
        },
-       
+
        specialAll: {
                live: {
                        setup: function( selector, namespaces ){
@@ -361,14 +354,14 @@ jQuery.event = {
                        },
                        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++;
                                        });
-                                       
-                                       if ( remove <= 1 )
+
+                                       if ( remove < 1 )
                                                jQuery.event.remove( this, namespaces[0], liveHandler );
                                }
                        }
@@ -380,19 +373,19 @@ jQuery.Event = function( 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;
-               this.timeStamp = src.timeStamp;
        // 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;
 };
@@ -448,7 +441,7 @@ var withinElement = function(event) {
        while ( parent && parent != this )
                try { parent = parent.parentNode; }
                catch(e) { parent = this; }
-       
+
        if( parent != this ){
                // set the correct event type
                event.type = event.data;
@@ -456,9 +449,9 @@ var withinElement = function(event) {
                jQuery.event.handle.apply( this, arguments );
        }
 };
-       
-jQuery.each({ 
-       mouseover: 'mouseenter', 
+
+jQuery.each({
+       mouseover: 'mouseenter',
        mouseout: 'mouseleave'
 }, function( orig, fix ){
        jQuery.event.special[ fix ] = {
@@ -468,7 +461,7 @@ jQuery.each({
                teardown: function(){
                        jQuery.event.remove( this, orig, withinElement );
                }
-       };                         
+       };
 });
 
 jQuery.fn.extend({
@@ -507,7 +500,7 @@ jQuery.fn.extend({
                        event.stopPropagation();
                        jQuery.event.trigger( event, data, this[0] );
                        return event.result;
-               }               
+               }
        },
 
        toggle: function( fn ) {
@@ -550,34 +543,50 @@ jQuery.fn.extend({
 
                return this;
        },
-       
+
        live: function( type, fn ){
-               jQuery(document).bind( liveConvert(type, this.selector), this.selector, fn );
+               var proxy = jQuery.event.proxy( fn );
+               proxy.guid += this.selector + type;
+
+               jQuery( this.context ).bind( liveConvert(type, this.selector), this.selector, proxy );
+
                return this;
        },
-       
+
        die: function( type, fn ){
-               jQuery(document).unbind( liveConvert(type, this.selector), fn );
+               jQuery( this.context ).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
                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){
                if ( check.test(fn.type) ) {
                        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;
 }
 
 function liveConvert(type, selector){
-       return ["live", type, selector.replace(/\./g, "_")].join(".");
+       return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
 }
 
 jQuery.extend({
@@ -634,7 +643,7 @@ function bindReady(){
 
                // 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 {
@@ -668,9 +677,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
-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 );
-}); 
+});