Update CommonJS module registration to check to see if define is a function instead...
[jquery.git] / src / core.js
index 3f156a5..4da1212 100644 (file)
@@ -1,3 +1,5 @@
+var jQuery = (function() {
+
 // Define a local copy of jQuery
 var jQuery = function( selector, context ) {
                // The jQuery object is actually just the init constructor 'enhanced'
@@ -10,29 +12,45 @@ var jQuery = function( selector, context ) {
        // Map over the $ in case of overwrite
        _$ = window.$,
 
-       // Use the correct document accordingly with window argument (sandbox)
-       document = window.document,
-
        // A central reference to the root jQuery(document)
        rootjQuery,
 
        // A simple way to check for HTML strings or ID strings
        // (both of which we optimize for)
-       quickExpr = /^[^<]*(<[\w\W]+>)[^>]*$|^#([\w\-]+)$/,
+       quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,
 
        // Is it a simple selector
        isSimple = /^.[^:#\[\.,]*$/,
 
        // Check if a string has a non-whitespace character in it
        rnotwhite = /\S/,
+       rwhite = /\s/,
 
        // Used for trimming whitespace
        trimLeft = /^\s+/,
        trimRight = /\s+$/,
 
+       // Check for non-word characters
+       rnonword = /\W/,
+
+       // Check for digits
+       rdigit = /\d/,
+
        // Match a standalone tag
        rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
 
+       // JSON RegExp
+       rvalidchars = /^[\],:{}\s]*$/,
+       rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
+       rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
+       rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+
+       // Useragent RegExp
+       rwebkit = /(webkit)[ \/]([\w.]+)/,
+       ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
+       rmsie = /(msie) ([\w.]+)/,
+       rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
+
        // Keep a UserAgent string for use with jQuery.browser
        userAgent = navigator.userAgent,
 
@@ -53,7 +71,11 @@ var jQuery = function( selector, context ) {
        hasOwn = Object.prototype.hasOwnProperty,
        push = Array.prototype.push,
        slice = Array.prototype.slice,
-       indexOf = Array.prototype.indexOf;
+       trim = String.prototype.trim,
+       indexOf = Array.prototype.indexOf,
+       
+       // [[Class]] -> type pairs
+       class2type = {};
 
 jQuery.fn = jQuery.prototype = {
        init: function( selector, context ) {
@@ -72,7 +94,7 @@ jQuery.fn = jQuery.prototype = {
                }
                
                // The body element only exists once, optimize finding it
-               if ( selector === "body" && !context ) {
+               if ( selector === "body" && !context && document.body ) {
                        this.context = document;
                        this[0] = document.body;
                        this.selector = "body";
@@ -106,7 +128,7 @@ jQuery.fn = jQuery.prototype = {
                                                }
 
                                        } else {
-                                               ret = buildFragment( [ match[1] ], [ doc ] );
+                                               ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
                                                selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
                                        }
                                        
@@ -116,7 +138,9 @@ jQuery.fn = jQuery.prototype = {
                                } else {
                                        elem = document.getElementById( match[2] );
 
-                                       if ( elem ) {
+                                       // 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] ) {
@@ -134,7 +158,7 @@ jQuery.fn = jQuery.prototype = {
                                }
 
                        // HANDLE: $("TAG")
-                       } else if ( !context && /^\w+$/.test( selector ) ) {
+                       } else if ( !context && !rnonword.test( selector ) ) {
                                this.selector = selector;
                                this.context = document;
                                selector = document.getElementsByTagName( selector );
@@ -191,7 +215,7 @@ jQuery.fn = jQuery.prototype = {
                        this.toArray() :
 
                        // Return just the object
-                       ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
+                       ( num < 0 ? this[ this.length + num ] : this[ num ] );
        },
 
        // Take an array of elements and push it onto the stack
@@ -287,8 +311,11 @@ jQuery.fn = jQuery.prototype = {
 jQuery.fn.init.prototype = jQuery.fn;
 
 jQuery.extend = jQuery.fn.extend = function() {
-       // copy reference to target object
-       var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy;
+        var options, name, src, copy, copyIsArray, clone,
+               target = arguments[0] || {},
+               i = 1,
+               length = arguments.length,
+               deep = false;
 
        // Handle a deep copy situation
        if ( typeof target === "boolean" ) {
@@ -322,10 +349,15 @@ jQuery.extend = jQuery.fn.extend = function() {
                                        continue;
                                }
 
-                               // Recurse if we're merging object literal values or arrays
-                               if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) {
-                                       var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src
-                                               : jQuery.isArray(copy) ? [] : {};
+                               // Recurse if we're merging plain objects or arrays
+                               if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+                                       if ( copyIsArray ) {
+                                               copyIsArray = false;
+                                               clone = src && jQuery.isArray(src) ? src : [];
+
+                                       } else {
+                                               clone = src && jQuery.isPlainObject(src) ? src : {};
+                                       }
 
                                        // Never move original objects, clone them
                                        target[ name ] = jQuery.extend( deep, clone, copy );
@@ -355,34 +387,51 @@ jQuery.extend({
        
        // Is the DOM ready to be used? Set to true once it occurs.
        isReady: false,
+
+       // A counter to track how many items to wait for before
+       // the ready event fires. See #6781
+       readyWait: 1,
        
        // Handle when the DOM is ready
-       ready: function() {
+       ready: function( wait ) {
+               // A third-party is pushing the ready event forwards
+               if ( wait === true ) {
+                       jQuery.readyWait--;
+               }
+
                // Make sure that the DOM is not already loaded
-               if ( !jQuery.isReady ) {
+               if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) {
                        // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
                        if ( !document.body ) {
-                               return setTimeout( jQuery.ready, 13 );
+                               return setTimeout( jQuery.ready, 1 );
                        }
 
                        // Remember that the DOM is ready
                        jQuery.isReady = true;
 
+                       // If a normal DOM Ready event fired, decrement, and wait if need be
+                       if ( wait !== true && --jQuery.readyWait > 0 ) {
+                               return;
+                       }
+
                        // If there are functions bound, to execute
                        if ( readyList ) {
                                // Execute all of them
-                               var fn, i = 0;
-                               while ( (fn = readyList[ i++ ]) ) {
-                                       fn.call( document, jQuery );
-                               }
+                               var fn,
+                                       i = 0,
+                                       ready = readyList;
 
                                // Reset the list of functions
                                readyList = null;
-                       }
 
-                       // Trigger any bound ready events
-                       if ( jQuery.fn.triggerHandler ) {
-                               jQuery( document ).triggerHandler( "ready" );
+                               while ( (fn = ready[ i++ ]) ) {
+                                       fn.call( document, jQuery );
+                               }
+
+                               // Trigger any bound ready events
+                               if ( jQuery.fn.trigger ) {
+                                       jQuery( document ).trigger( "ready" ).unbind( "ready" );
+                               }
                        }
                }
        },
@@ -397,7 +446,8 @@ jQuery.extend({
                // Catch cases where $(document).ready() is called after the
                // browser event has already occurred.
                if ( document.readyState === "complete" ) {
-                       return jQuery.ready();
+                       // Handle it asynchronously to allow scripts the opportunity to delay ready
+                       return setTimeout( jQuery.ready, 1 );
                }
 
                // Mozilla, Opera and webkit nightlies currently support this event
@@ -435,18 +485,33 @@ jQuery.extend({
        // Since version 1.3, DOM methods and functions like alert
        // aren't supported. They return false on IE (#2968).
        isFunction: function( obj ) {
-               return toString.call(obj) === "[object Function]";
+               return jQuery.type(obj) === "function";
        },
 
-       isArray: function( obj ) {
-               return toString.call(obj) === "[object Array]";
+       isArray: Array.isArray || function( obj ) {
+               return jQuery.type(obj) === "array";
+       },
+
+       // A crude way of determining if an object is a window
+       isWindow: function( obj ) {
+               return obj && typeof obj === "object" && "setInterval" in obj;
+       },
+
+       isNaN: function( obj ) {
+               return obj == null || !rdigit.test( obj ) || isNaN( obj );
+       },
+
+       type: function( obj ) {
+               return obj == null ?
+                       String( obj ) :
+                       class2type[ toString.call(obj) ] || "object";
        },
 
        isPlainObject: function( obj ) {
                // Must be an Object.
                // Because of IE, we also have to check the presence of the constructor property.
                // Make sure that DOM nodes and window objects don't pass through, as well
-               if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) {
+               if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
                        return false;
                }
                
@@ -487,9 +552,9 @@ jQuery.extend({
                
                // Make sure the incoming data is actual JSON
                // Logic borrowed from http://json.org/json2.js
-               if ( /^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
-                       .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
-                       .replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) {
+               if ( rvalidchars.test(data.replace(rvalidescape, "@")
+                       .replace(rvalidtokens, "]")
+                       .replace(rvalidbraces, "")) ) {
 
                        // Try to use the native JSON parser first
                        return window.JSON && window.JSON.parse ?
@@ -569,11 +634,11 @@ jQuery.extend({
        },
 
        // Use native String.trim function wherever possible
-       trim: String.trim ?
+       trim: trim ?
                function( text ) {
                        return text == null ?
                                "" :
-                               String.trim( text );
+                               trim.call( text );
                } :
 
                // Otherwise use our own trimming functionality
@@ -591,7 +656,10 @@ jQuery.extend({
                        // The window, strings (and functions) also have 'length'
                        // The extra typeof function check is to prevent crashes
                        // in Safari 2 (See: #3039)
-                       if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) {
+                       // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
+                       var type = jQuery.type(array);
+
+                       if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
                                push.call( ret, array );
                        } else {
                                jQuery.merge( ret, array );
@@ -616,7 +684,8 @@ jQuery.extend({
        },
 
        merge: function( first, second ) {
-               var i = first.length, j = 0;
+               var i = first.length,
+                       j = 0;
 
                if ( typeof second.length === "number" ) {
                        for ( var l = second.length; j < l; j++ ) {
@@ -664,6 +733,7 @@ jQuery.extend({
                        }
                }
 
+               // Flatten any nested arrays
                return ret.concat.apply( [], ret );
        },
 
@@ -698,15 +768,48 @@ jQuery.extend({
                return proxy;
        },
 
+       // Mutifunctional method to get and set values to a collection
+       // The value/s can be optionally by executed if its a function
+       access: function( elems, key, value, exec, fn, pass ) {
+               var length = elems.length;
+       
+               // Setting many attributes
+               if ( typeof key === "object" ) {
+                       for ( var k in key ) {
+                               jQuery.access( elems, k, key[k], exec, fn, value );
+                       }
+                       return elems;
+               }
+       
+               // Setting one attribute
+               if ( value !== undefined ) {
+                       // Optionally, function values get executed if exec is true
+                       exec = !pass && exec && jQuery.isFunction(value);
+               
+                       for ( var i = 0; i < length; i++ ) {
+                               fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
+                       }
+               
+                       return elems;
+               }
+       
+               // Getting an attribute
+               return length ? fn( elems[0], key ) : undefined;
+       },
+
+       now: function() {
+               return (new Date()).getTime();
+       },
+
        // Use of jQuery.browser is frowned upon.
        // More details: http://docs.jquery.com/Utilities/jQuery.browser
        uaMatch: function( ua ) {
                ua = ua.toLowerCase();
 
-               var match = /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
-                       /(opera)(?:.*version)?[ \/]([\w.]+)/.exec( ua ) ||
-                       /(msie) ([\w.]+)/.exec( ua ) ||
-                       !/compatible/.test( ua ) && /(mozilla)(?:.*? rv:([\w.]+))?/.exec( ua ) ||
+               var match = rwebkit.exec( ua ) ||
+                       ropera.exec( ua ) ||
+                       rmsie.exec( ua ) ||
+                       ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
                        [];
 
                return { browser: match[1] || "", version: match[2] || "0" };
@@ -715,6 +818,11 @@ jQuery.extend({
        browser: {}
 });
 
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
+       class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
 browserMatch = jQuery.uaMatch( userAgent );
 if ( browserMatch.browser ) {
        jQuery.browser[ browserMatch.browser ] = true;
@@ -734,7 +842,7 @@ if ( indexOf ) {
 
 // Verify that \s matches non-breaking spaces
 // (IE fails on this test)
-if ( !/\s/.test( "\xA0" ) ) {
+if ( !rwhite.test( "\xA0" ) ) {
        trimLeft = /^[\s\xA0]+/;
        trimRight = /[\s\xA0]+$/;
 }
@@ -778,51 +886,12 @@ function doScrollCheck() {
        jQuery.ready();
 }
 
-function evalScript( i, elem ) {
-       if ( elem.src ) {
-               jQuery.ajax({
-                       url: elem.src,
-                       async: false,
-                       dataType: "script"
-               });
-       } else {
-               jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
-       }
-
-       if ( elem.parentNode ) {
-               elem.parentNode.removeChild( elem );
-       }
+// Expose jQuery as an Asynchronous Module
+if ( typeof define === "function" ) {
+       define( "jquery", [], function () { return jQuery; } );
 }
 
-// Mutifunctional method to get and set values to a collection
-// The value/s can be optionally by executed if its a function
-function access( elems, key, value, exec, fn, pass ) {
-       var length = elems.length;
-       
-       // Setting many attributes
-       if ( typeof key === "object" ) {
-               for ( var k in key ) {
-                       access( elems, k, key[k], exec, fn, value );
-               }
-               return elems;
-       }
-       
-       // Setting one attribute
-       if ( value !== undefined ) {
-               // Optionally, function values get executed if exec is true
-               exec = !pass && exec && jQuery.isFunction(value);
-               
-               for ( var i = 0; i < length; i++ ) {
-                       fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
-               }
-               
-               return elems;
-       }
-       
-       // Getting an attribute
-       return length ? fn( elems[0], key ) : undefined;
-}
+// Expose jQuery to the global object
+return (window.jQuery = window.$ = jQuery);
 
-function now() {
-       return (new Date()).getTime();
-}
+})();