Merging in jQuery.proxy() branch.
authorjeresig <jeresig@gmail.com>
Wed, 6 Jan 2010 00:18:39 +0000 (19:18 -0500)
committerjeresig <jeresig@gmail.com>
Wed, 6 Jan 2010 00:18:39 +0000 (19:18 -0500)
1  2 
src/core.js
src/event.js
test/unit/core.js

diff --combined src/core.js
@@@ -33,10 -33,7 +33,10 @@@ var jQuery = function( selector, contex
        rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
  
        // Keep a UserAgent string for use with jQuery.browser
 -      userAgent = navigator.userAgent.toLowerCase(),
 +      userAgent = navigator.userAgent,
 +
 +      // For matching the engine and version of thte browser
 +      browserMatch,
        
        // Has the ready events already been bound?
        readyBound = false,
@@@ -467,8 -464,6 +467,8 @@@ jQuery.extend(
                return true;
        },
  
 +      noop: function() {},
 +
        // Evalulates a script in a global context
        globalEval: function( data ) {
                if ( data && rnotwhite.test(data) ) {
                return ret.concat.apply( [], ret );
        },
  
+       // A global GUID counter for objects
+       guid: 1,
+       proxy: function( fn, proxy, thisObject ) {
+               if ( arguments.length === 2 ) {
+                       if ( typeof proxy === "string" ) {
+                               thisObject = fn;
+                               fn = thisObject[ proxy ];
+                               proxy = undefined;
+                       } else if ( proxy && !jQuery.isFunction( proxy ) ) {
+                               thisObject = proxy;
+                               proxy = undefined;
+                       }
+               }
+               if ( !proxy && fn ) {
+                       proxy = function() {
+                               return fn.apply( thisObject || this, arguments );
+                       };
+               }
+               // Set the guid of unique handler to the same of original handler, so it can be removed
+               if ( fn ) {
+                       proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
+               }
+               // So proxy can be declared as an argument
+               return proxy;
+       },
        // Use of jQuery.browser is frowned upon.
        // More details: http://docs.jquery.com/Utilities/jQuery.browser
 -      browser: {
 -              version: (/.*?(?:firefox|safari|opera|msie)[\/ ]([\d.]+)/.exec(userAgent) || [0,"0"])[1],
 -              safari: /safari/.test( userAgent ),
 -              opera: /opera/.test( userAgent ),
 -              msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
 -              firefox: /firefox/.test( userAgent )
 -      }
 +      uaMatch: function( ua ) {
 +              var ret = { browser: "" };
 +
 +              ua = ua.toLowerCase();
 +
 +              if ( /webkit/.test( ua ) ) {
 +                      ret = { browser: "webkit", version: /webkit[\/ ]([\w.]+)/ };
 +
 +              } else if ( /opera/.test( ua ) ) {
 +                      ret = { browser: "opera", version: /opera[\/ ]([\w.]+)/ };
 +
 +              } else if ( /msie/.test( ua ) ) {
 +                      ret = { browser: "msie", version: /msie ([\w.]+)/ };
 +
 +              } else if ( /mozilla/.test( ua ) && !/compatible/.test( ua ) ) {
 +                      ret = { browser: "mozilla", version: /rv:([\w.]+)/ };
 +              }
 +
 +              ret.version = (ret.version && ret.version.exec( ua ) || [0, "0"])[1];
 +
 +              return ret;
 +      },
 +
 +      browser: {}
  });
  
 -// Deprecated
 -jQuery.browser.mozilla = /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent );
 +browserMatch = jQuery.uaMatch( userAgent );
 +if ( browserMatch.browser ) {
 +      jQuery.browser[ browserMatch.browser ] = true;
 +      jQuery.browser.version = browserMatch.version;
 +}
 +
 +// Deprecated, use jQuery.browser.webkit instead
 +if ( jQuery.browser.webkit ) {
 +      jQuery.browser.safari = true;
 +}
  
  if ( indexOf ) {
        jQuery.inArray = function( elem, array ) {
diff --combined src/event.js
@@@ -26,7 -26,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
@@@ -35,7 -35,7 +35,7 @@@
                        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;
                elem = null;
        },
  
-       guid: 1,
        global: {},
  
        // Detach an event or set of events from an element
                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 );
-               };
+       // Deprecated, use jQuery.guid instead
+       guid: 1E8,
  
-               // 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.proxy instead
+       proxy: jQuery.proxy,
  
        special: {
                ready: {
                        // Make sure the ready event is setup
                        setup: jQuery.bindReady,
 -                      teardown: function() {}
 +                      teardown: jQuery.noop
                },
  
                live: {
@@@ -759,7 -746,7 +746,7 @@@ if ( document.addEventListener ) 
  }
  
  jQuery.each(["bind", "one"], function( i, name ) {
-       jQuery.fn[ name ] = function( type, data, fn, thisObject ) {
+       jQuery.fn[ name ] = function( type, data, fn ) {
                // Handle object literals
                if ( typeof type === "object" ) {
                        for ( var key in type ) {
                        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) : 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 );
 +                      });
        };
  });
  
@@@ -822,10 -808,10 +810,10 @@@ jQuery.fn.extend(
  
                // link all the functions, so any of them can unbind this click handler
                while ( i < args.length ) {
-                       jQuery.event.proxy( fn, args[ i++ ] );
+                       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 );
                return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
        },
  
-       live: function( type, data, fn, thisObject ) {
+       live: function( type, data, fn ) {
                if ( jQuery.isFunction( data ) ) {
                        fn = data;
                        data = undefined;
                }
                jQuery( this.context ).bind( liveConvert( type, this.selector ), {
                        data: data, selector: this.selector, live: type
-               }, fn, thisObject );
+               }, fn );
                return this;
        },
  
diff --combined test/unit/core.js
@@@ -154,27 -154,41 +154,27 @@@ test("selector state", function() 
        );
  });
  
 +if ( !isLocal ) {
  test("browser", function() {
 -      expect(13);
 -      var browsers = {
 -              //Internet Explorer
 -              "Mozilla/5.0 (Windows; U; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)": "6.0",
 -              "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.1; .NET CLR 1.1.4322; InfoPath.1; .NET CLR 2.0.50727)": "7.0",
 -              /** Failing #1876
 -               * "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30)": "7.0",
 -               */
 -              //Browsers with Gecko engine
 -              //Mozilla
 -              "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915" : "1.7.12",
 -              //Firefox
 -              "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3": "1.8.1.3",
 -              //Netscape
 -              "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20070321 Netscape/8.1.3" : "1.7.5",
 -              //Flock
 -              "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.11) Gecko/20070321 Firefox/1.5.0.11 Flock/0.7.12" : "1.8.0.11",
 -              //Opera browser
 -              "Opera/9.20 (X11; Linux x86_64; U; en)": "9.20",
 -              "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.20" : "9.20",
 -              "Mozilla/5.0 (Windows NT 5.1; U; pl; rv:1.8.0) Gecko/20060728 Firefox/1.5.0 Opera 9.20": "9.20",
 -              //WebKit engine
 -              "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; sv-se) AppleWebKit/418.9 (KHTML, like Gecko) Safari/419.3": "418.9",
 -              "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.8 (KHTML, like Gecko) Safari/419.3" : "418.8",
 -              "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; sv-se) AppleWebKit/312.8 (KHTML, like Gecko) Safari/312.5": "312.8",
 -              //Other user agent string
 -              "Other browser's user agent 1.0":null
 -      };
 -      for (var i in browsers) {
 -              var v = i.toLowerCase().match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ); // RegEx from Core jQuery.browser.version check
 -              var version = v ? v[1] : null;
 -              equals( version, browsers[i], "Checking UA string" );
 -      }
 +      stop();
 +
 +      jQuery.get("data/ua.txt", function(data){
 +              var uas = data.split("\n");
 +              expect( (uas.length - 1) * 2 );
 +
 +              jQuery.each(uas, function(){
 +                      var parts = this.split("\t");
 +                      if ( parts[2] ) {
 +                              var ua = jQuery.uaMatch( parts[2] );
 +                              equals( ua.browser, parts[0], "Checking browser for " + parts[2] );
 +                              equals( ua.version, parts[1], "Checking version string for " + parts[2] );
 +                      }
 +              });
 +
 +              start();
 +      });
  });
 +}
  
  test("noConflict", function() {
        expect(6);
@@@ -825,3 -839,22 +825,22 @@@ test("jQuery.isEmptyObject", function()
        // What about this ?
        // equals(true, jQuery.isEmptyObject(null), "isEmptyObject on null" );
  });
+ test("jQuery.proxy", function(){
+       expect(4);
+       var test = function(){ equals( this, thisObject, "Make sure that scope is set properly." ); };
+       var thisObject = { foo: "bar", method: test };
+       // Make sure normal works
+       test.call( thisObject );
+       // Basic scoping
+       jQuery.proxy( test, thisObject )();
+       // Make sure it doesn't freak out
+       equals( jQuery.proxy( null, thisObject ), undefined, "Make sure no function was returned." );
+       // Use the string shortcut
+       jQuery.proxy( thisObject, "method" )();
+ });