X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=src%2Fcore.js;h=2e63472361b150b3e2abcce9111ca1eb65b0eb48;hb=4a828c93d40eb67b2041b08bbed0f1973442bd03;hp=48261fc4fed0584df579d731b0251708609955a6;hpb=c475222bfb729d7629cece87cf1cc96aaaacd305;p=jquery.git diff --git a/src/core.js b/src/core.js index 48261fc..2e63472 100644 --- a/src/core.js +++ b/src/core.js @@ -15,8 +15,9 @@ var jQuery = function( selector, context ) { // A central reference to the root jQuery(document) rootjQuery, - // A simple way to check for HTML strings - quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$/, + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, // Check if a string has a non-whitespace character in it rnotwhite = /\S/, @@ -25,9 +26,6 @@ var jQuery = function( selector, context ) { trimLeft = /^\s+/, trimRight = /\s+$/, - // Check for non-word characters - rnonword = /\W/, - // Check for digits rdigit = /\d/, @@ -58,8 +56,16 @@ var jQuery = function( selector, context ) { // The deferred used on DOM ready readyList, - // Promise methods - promiseMethods = "then done fail isResolved isRejected promise".split( " " ), + // Promise methods (with equivalent for invert) + promiseMethods = { + then: 0, // will be overwritten for invert + done: "fail", + fail: "done", + isResolved: "isRejected", + isRejected: "isResolved", + promise: "invert", + invert: "promise" + }, // The ready event handler DOMContentLoaded, @@ -92,32 +98,70 @@ jQuery.fn = jQuery.prototype = { return this; } + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = "body"; + this.length = 1; + return this; + } + // Handle HTML strings if ( typeof selector === "string" ) { - // Are we dealing with HTML string - if ( (match = quickExpr.exec( selector )) ) { - context = context instanceof jQuery ? context[0] : context; - doc = (context ? context.ownerDocument || context : document); + // Are we dealing with HTML string or an ID? + match = quickExpr.exec( selector ); - // If a single string is passed in and it's a single tag - // just do a createElement and skip the rest - ret = rsingleTag.exec( selector ); + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { - if ( ret ) { - if ( jQuery.isPlainObject( context ) ) { - selector = [ document.createElement( ret[1] ) ]; - jQuery.fn.attr.call( selector, context, true ); + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } } else { - selector = [ doc.createElement( ret[1] ) ]; + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; } + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") } else { - ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); - selector = (ret.cacheable ? jQuery(ret.fragment).clone()[0] : ret.fragment).childNodes; - } + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } - return jQuery.merge( this, selector ); + this.context = document; + this.selector = selector; + return this; + } // HANDLE: $(expr, $(...)) } else if ( !context || context.jquery ) { @@ -208,12 +252,14 @@ jQuery.fn = jQuery.prototype = { return jQuery.each( this, callback, args ); }, - ready: function() { + ready: function( fn ) { // Attach the listeners jQuery.bindReady(); - // Change ready & apply - return ( jQuery.fn.ready = readyList.done ).apply( this , arguments ); + // Add the callback + readyList.done( fn ); + + return this; }, eq: function( i ) { @@ -360,7 +406,7 @@ jQuery.extend({ } // If there are functions bound, to execute - readyList.fire( document , [ jQuery ] ); + readyList.resolveWith( document, [ jQuery ] ); // Trigger any bound ready events if ( jQuery.fn.trigger ) { @@ -528,10 +574,8 @@ jQuery.extend({ if ( data && rnotwhite.test(data) ) { // Inspired by code by Andrea Giammarchi // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html - var head = document.getElementsByTagName("head")[0] || document.documentElement, - script = document.createElement("script"); - - script.type = "text/javascript"; + var head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement, + script = document.createElement( "script" ); if ( jQuery.support.scriptEval() ) { script.appendChild( document.createTextNode( data ) ); @@ -758,7 +802,6 @@ jQuery.extend({ // Create a simple deferred (one callbacks list) _Deferred: function() { - var // callbacks list callbacks = [], // stored [ context , args ] @@ -771,53 +814,45 @@ jQuery.extend({ deferred = { // done( f1, f2, ...) - done: function () { - - if ( ! cancelled ) { - + done: function() { + if ( !cancelled ) { var args = arguments, i, length, elem, type, _fired; - if ( fired ) { _fired = fired; fired = 0; } - - for ( i = 0, length = args.length ; i < length ; i++ ) { + for ( i = 0, length = args.length; i < length; i++ ) { elem = args[ i ]; type = jQuery.type( elem ); if ( type === "array" ) { - deferred.done.apply( deferred , elem ); + deferred.done.apply( deferred, elem ); } else if ( type === "function" ) { callbacks.push( elem ); } } - if ( _fired ) { - deferred.fire( _fired[ 0 ] , _fired[ 1 ] ); + deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); } } - return this; }, // resolve with given context and args - fire: function( context , args ) { - if ( ! cancelled && ! fired && ! firing ) { - + resolveWith: function( context, args ) { + if ( !cancelled && !fired && !firing ) { firing = 1; - try { while( callbacks[ 0 ] ) { - callbacks.shift().apply( context , args ); + callbacks.shift().apply( context, args ); } } finally { - fired = [ context , args ]; + fired = [ context, args ]; firing = 0; } } @@ -826,7 +861,7 @@ jQuery.extend({ // resolve with this as context and given arguments resolve: function() { - deferred.fire( jQuery.isFunction( this.promise ) ? this.promise() : this , arguments ); + deferred.resolveWith( jQuery.isFunction( this.promise ) ? this.promise() : this, arguments ); return this; }, @@ -847,54 +882,62 @@ jQuery.extend({ }, // Full fledged deferred (two callbacks list) - // Typical success/error system Deferred: function( func ) { - var deferred = jQuery._Deferred(), failDeferred = jQuery._Deferred(), - promise; - - // Add errorDeferred methods, then and promise - jQuery.extend( deferred , { - - then: function( doneCallbacks , failCallbacks ) { + promise, + invert; + // Add errorDeferred methods, then, promise and invert + jQuery.extend( deferred, { + then: function( doneCallbacks, failCallbacks ) { deferred.done( doneCallbacks ).fail( failCallbacks ); return this; }, fail: failDeferred.done, - fireReject: failDeferred.fire, + rejectWith: failDeferred.resolveWith, reject: failDeferred.resolve, isRejected: failDeferred.isResolved, // Get a promise for this deferred // If obj is provided, the promise aspect is added to the object - // (i is used internally) - promise: function( obj , i ) { + promise: function( obj ) { if ( obj == null ) { if ( promise ) { return promise; } promise = obj = {}; } - i = promiseMethods.length; - while( i-- ) { - obj[ promiseMethods[ i ] ] = deferred[ promiseMethods[ i ] ]; + for( var methodName in promiseMethods ) { + obj[ methodName ] = deferred[ methodName ]; + } + return obj; + }, + // Get the invert promise for this deferred + // If obj is provided, the invert promise aspect is added to the object + invert: function( obj ) { + if ( obj == null ) { + if ( invert ) { + return invert; + } + invert = obj = {}; + } + for( var methodName in promiseMethods ) { + obj[ methodName ] = promiseMethods[ methodName ] && deferred[ promiseMethods[methodName] ]; } + obj.then = invert.then || function( doneCallbacks, failCallbacks ) { + deferred.done( failCallbacks ).fail( doneCallbacks ); + return this; + }; return obj; } - } ); - // Make sure only one callback list will be used - deferred.then( failDeferred.cancel , deferred.cancel ); - + deferred.then( failDeferred.cancel, deferred.cancel ); // Unexpose cancel delete deferred.cancel; - // Call given func if any if ( func ) { - func.call( deferred , deferred ); + func.call( deferred, deferred ); } - return deferred; }, @@ -910,18 +953,14 @@ jQuery.extend({ if ( length > 1 ) { resolveArray = new Array( length ); - jQuery.each( args, function( index, element, args ) { - jQuery.when( element ).done( function( value ) { - args = arguments; - resolveArray[ index ] = args.length > 1 ? slice.call( args , 0 ) : value; + jQuery.each( args, function( index, element ) { + jQuery.when( element ).then( function( value ) { + resolveArray[ index ] = arguments.length > 1 ? slice.call( arguments, 0 ) : value; if( ! --length ) { - deferred.fire( promise, resolveArray ); + deferred.resolveWith( promise, resolveArray ); } - }).fail( function() { - deferred.fireReject( promise, arguments ); - }); - return !deferred.isRejected(); - }); + }, deferred.reject ); + } ); } else if ( deferred !== object ) { deferred.resolve( object ); } @@ -942,18 +981,20 @@ jQuery.extend({ return { browser: match[1] || "", version: match[2] || "0" }; }, - subclass: function(){ + sub: function() { function jQuerySubclass( selector, context ) { return new jQuerySubclass.fn.init( selector, context ); } + jQuery.extend( true, jQuerySubclass, this ); jQuerySubclass.superclass = this; jQuerySubclass.fn = jQuerySubclass.prototype = this(); jQuerySubclass.fn.constructor = jQuerySubclass; jQuerySubclass.subclass = this.subclass; jQuerySubclass.fn.init = function init( selector, context ) { - if (context && context instanceof jQuery && !(context instanceof jQuerySubclass)){ + if ( context && context instanceof jQuery && !(context instanceof jQuerySubclass) ) { context = jQuerySubclass(context); } + return jQuery.fn.init.call( this, selector, context, rootjQuerySubclass ); }; jQuerySubclass.fn.init.prototype = jQuerySubclass.fn;