Fixed typo in logic, also disabled function setters in this case to allow the functi...
[jquery.git] / src / event.js
index a4eebf5..0234998 100644 (file)
@@ -1,3 +1,9 @@
+var fcleanup = function( nm ) {
+       return nm.replace(/[^\w\s\.\|`]/g, function( ch ) {
+               return "\\" + ch;
+       });
+};
+
 /*
  * A number of helper functions used for managing events.
  * Many of the ideas behind this code originated from
@@ -20,7 +26,7 @@ jQuery.event = {
 
                // Make sure that the function being executed has a unique ID
                if ( !handler.guid ) {
-                       handler.guid = this.guid++;
+                       handler.guid = jQuery.guid++;
                }
 
                // if data is passed, bind to handler
@@ -29,7 +35,7 @@ jQuery.event = {
                        var fn = handler;
 
                        // Create unique handler function, wrapped around original handler
-                       handler = this.proxy( fn );
+                       handler = jQuery.proxy( fn );
 
                        // Store data in unique handler
                        handler.data = data;
@@ -108,7 +114,6 @@ jQuery.event = {
                elem = null;
        },
 
-       guid: 1,
        global: {},
 
        // Detach an event or set of events from an element
@@ -142,7 +147,7 @@ jQuery.event = {
                                        var namespaces = type.split(".");
                                        type = namespaces.shift();
                                        var all = !namespaces.length,
-                                               cleaned = jQuery.map( namespaces.slice(0).sort() , function(nm){ return nm.replace(/[^\w\s\.\|`]/g, function(ch){return "\\"+ch;  }); }),
+                                               cleaned = jQuery.map( namespaces.slice(0).sort(), fcleanup ),
                                                namespace = new RegExp("(^|\\.)" + cleaned.join("\\.(?:.*\\.)?") + "(\\.|$)"),
                                                special = this.special[ type ] || {};
 
@@ -224,6 +229,7 @@ jQuery.event = {
                        if ( !elem ) {
                                // Don't bubble custom events when global (to avoid too much overhead)
                                event.stopPropagation();
+
                                // Only trigger if we've ever bound an event for it
                                if ( this.global[ type ] ) {
                                        jQuery.each( jQuery.cache, function() {
@@ -389,7 +395,7 @@ jQuery.event = {
                        event.metaKey = event.ctrlKey;
                }
 
-               // Add which for click: 1 == left; 2 == middle; 3 == right
+               // Add which for click: 1 === left; 2 === middle; 3 === right
                // Note: button is not normalized, so don't use it
                if ( !event.which && event.button !== undefined ) {
                        event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
@@ -398,24 +404,17 @@ jQuery.event = {
                return event;
        },
 
-       proxy: function( fn, proxy, thisObject ) {
-               if ( proxy !== undefined && !jQuery.isFunction( proxy ) ) {
-                       thisObject = proxy;
-                       proxy = undefined;
-               }
-               // FIXME: Should proxy be redefined to be applied with thisObject if defined?
-               proxy = proxy || function() { return fn.apply( thisObject !== undefined ? thisObject : 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
-               return proxy;
-       },
+       // Deprecated, use jQuery.guid instead
+       guid: 1E8,
+
+       // Deprecated, use jQuery.proxy instead
+       proxy: jQuery.proxy,
 
        special: {
                ready: {
                        // Make sure the ready event is setup
                        setup: jQuery.bindReady,
-                       teardown: function() {}
+                       teardown: jQuery.noop
                },
 
                live: {
@@ -462,7 +461,7 @@ jQuery.event = {
        }
 };
 
-jQuery.Event = function( src ){
+jQuery.Event = function( src ) {
        // Allow instantiation without the 'new' keyword
        if ( !this.preventDefault ) {
                return new jQuery.Event( src );
@@ -524,7 +523,7 @@ jQuery.Event.prototype = {
                // otherwise set the cancelBubble property of the original event to true (IE)
                e.cancelBubble = true;
        },
-       stopImmediatePropagation: function(){
+       stopImmediatePropagation: function() {
                this.isImmediatePropagationStopped = returnTrue;
                this.stopPropagation();
        },
@@ -532,23 +531,30 @@ jQuery.Event.prototype = {
        isPropagationStopped: returnFalse,
        isImmediatePropagationStopped: returnFalse
 };
+
 // Checks if an event happened on an element within another element
 // Used in jQuery.event.special.mouseenter and mouseleave handlers
 var withinElement = function( event ) {
        // Check if mouse(over|out) are still within the same parent element
        var parent = event.relatedTarget;
+
        // Traverse up the tree
-       while ( parent && parent != this ) {
+       while ( parent && parent !== this ) {
                // Firefox sometimes assigns relatedTarget a XUL element
                // which we cannot access the parentNode property of
-               try { parent = parent.parentNode; }
+               try {
+                       parent = parent.parentNode;
+
                // assuming we've left the element since we most likely mousedover a xul element
-               catch(e) { break; }
+               } catch(e) {
+                       break;
+               }
        }
 
-       if ( parent != this ) {
+       if ( parent !== this ) {
                // set the correct event type
                event.type = event.data;
+
                // handle event if we actually just moused on to a non sub-element
                jQuery.event.handle.apply( this, arguments );
        }
@@ -568,10 +574,10 @@ jQuery.each({
        mouseleave: "mouseout"
 }, function( orig, fix ) {
        jQuery.event.special[ orig ] = {
-               setup: function(data){
+               setup: function( data ) {
                        jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
                },
-               teardown: function(data){
+               teardown: function( data ) {
                        jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
                }
        };
@@ -598,6 +604,9 @@ jQuery.event.special.submit = {
                                        return trigger( "submit", this, arguments );
                                }
                        });
+
+               } else {
+                       return false;
                }
        },
 
@@ -672,7 +681,7 @@ jQuery.event.special.change = {
                },
 
                // Change has to be called before submit
-               // Keydown will be called before keypress, wich is used in submit-event delegation
+               // Keydown will be called before keypress, which is used in submit-event delegation
                keydown: function( e ) {
                        var elem = e.target, type = elem.type;
 
@@ -721,7 +730,7 @@ function trigger( type, elem, args ) {
 
 // Create "bubbling" focus and blur events
 if ( document.addEventListener ) {
-       jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ){
+       jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
                jQuery.event.special[ fix ] = {
                        setup: function() {
                                this.addEventListener( orig, handler, true );
@@ -739,8 +748,8 @@ if ( document.addEventListener ) {
        });
 }
 
-jQuery.each(["bind", "one"], function(i, name) {
-       jQuery.fn[ name ] = function( type, data, fn, thisObject ) {
+jQuery.each(["bind", "one"], function( i, name ) {
+       jQuery.fn[ name ] = function( type, data, fn ) {
                // Handle object literals
                if ( typeof type === "object" ) {
                        for ( var key in type ) {
@@ -754,14 +763,17 @@ jQuery.each(["bind", "one"], function(i, name) {
                        fn = data;
                        data = undefined;
                }
-               fn = thisObject === undefined ? fn : jQuery.event.proxy( fn, thisObject );
-               var handler = name == "one" ? jQuery.event.proxy( fn, function( event ) {
+
+               var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
                        jQuery( this ).unbind( event, handler );
                        return fn.apply( this, arguments );
                }) : fn;
-               return type === "unload" ? this.one(type, data, handler, thisObject) : this.each(function() {
-                       jQuery.event.add( this, type, handler, data );
-               });
+
+               return type === "unload" && name !== "one" ?
+                       this.one( type, data, fn, thisObject ) :
+                       this.each(function() {
+                               jQuery.event.add( this, type, handler, data );
+                       });
        };
 });
 
@@ -800,14 +812,14 @@ jQuery.fn.extend({
                var args = arguments, i = 1;
 
                // link all the functions, so any of them can unbind this click handler
-               while( i < args.length ) {
-                       jQuery.event.proxy( fn, args[ i++ ] );
+               while ( i < args.length ) {
+                       jQuery.proxy( fn, args[ i++ ] );
                }
 
-               return this.click( jQuery.event.proxy( fn, function( event ) {
+               return this.click( jQuery.proxy( fn, function( event ) {
                        // Figure out which function to execute
-                       var lastToggle = ( jQuery.data( this, 'lastToggle' + fn.guid ) || 0 ) % i;
-                       jQuery.data( this, 'lastToggle' + fn.guid, lastToggle + 1 );
+                       var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+                       jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
 
                        // Make sure that clicks stop
                        event.preventDefault();
@@ -821,17 +833,16 @@ jQuery.fn.extend({
                return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
        },
 
-       live: function( type, data, fn, thisObject ) {
+       live: function( type, data, fn ) {
                if ( jQuery.isFunction( data ) ) {
-                       if ( fn !== undefined ) {
-                               thisObject = fn;
-                       }
                        fn = data;
                        data = undefined;
                }
+
                jQuery( this.context ).bind( liveConvert( type, this.selector ), {
                        data: data, selector: this.selector, live: type
-               }, fn, thisObject );
+               }, fn );
+
                return this;
        },
 
@@ -899,7 +910,7 @@ function liveConvert( type, selector ) {
        return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "&")].join(".");
 }
 
-jQuery.each( ("blur focus load resize scroll unload click dblclick " +
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
        "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
        "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
 
@@ -908,8 +919,8 @@ jQuery.each( ("blur focus load resize scroll unload click dblclick " +
                return fn ? this.bind( name, fn ) : this.trigger( name );
        };
 
-       if ( jQuery.fnAttr ) {
-               jQuery.fnAttr[ name ] = true;
+       if ( jQuery.attrFn ) {
+               jQuery.attrFn[ name ] = true;
        }
 });