From: jeresig Date: Wed, 6 Jan 2010 00:18:39 +0000 (-0500) Subject: Merging in jQuery.proxy() branch. X-Git-Url: http://git.asbjorn.biz/?a=commitdiff_plain;h=230614b4df313493813d688b63ab68f3812a0030;hp=-c;p=jquery.git Merging in jQuery.proxy() branch. --- 230614b4df313493813d688b63ab68f3812a0030 diff --combined src/core.js index 8bd8044,3b6cfff..975d23c --- a/src/core.js +++ b/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) ) { @@@ -619,44 -614,50 +619,75 @@@ 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 index 64b202d,7d60c27..fe98794 --- a/src/event.js +++ b/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; @@@ -114,7 -114,6 +114,6 @@@ elem = null; }, - guid: 1, global: {}, // Detach an event or set of events from an element @@@ -405,29 -404,17 +404,17 @@@ 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 ) { @@@ -773,16 -760,15 +760,17 @@@ 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 ); @@@ -842,17 -828,16 +830,16 @@@ 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 index 3020543,eb00f23..d50997b --- a/test/unit/core.js +++ b/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" )(); + });