Changed .get(-Number) to use .slice() instead of .toArray() (which doesn't take any...
[jquery.git] / src / core.js
index 23b4a57..cb9b528 100644 (file)
@@ -1,8 +1,10 @@
-// Will speed up references to window, and allows munging its name.
-var window = this,
-
-       // Will speed up references to undefined, and allows munging its name.
-       undefined,
+// Define a local copy of jQuery
+var jQuery = function( selector, context ) {
+               // The jQuery object is actually just the init constructor 'enhanced'
+               return arguments.length === 0 ?
+                       rootjQuery :
+                       new jQuery.fn.init( selector, context );
+       },
 
        // Map over jQuery in case of overwrite
        _jQuery = window.jQuery,
@@ -10,19 +12,12 @@ var window = this,
        // Map over the $ in case of overwrite
        _$ = window.$,
 
-       // Define a local copy of jQuery
-       jQuery,
+       // Use the correct document accordingly with window argument (sandbox)
+       document = window.document,
 
        // A central reference to the root jQuery(document)
        rootjQuery,
 
-       jQuery = window.jQuery = window.$ = function( selector, context ) {
-               // The jQuery object is actually just the init constructor 'enhanced'
-               return arguments.length === 0 ?
-                       rootjQuery :
-                       new jQuery.fn.init( selector, context );
-       },
-
        // A simple way to check for HTML strings or ID strings
        // (both of which we optimize for)
        quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
@@ -30,27 +25,34 @@ var window = this,
        // Is it a simple selector
        isSimple = /^.[^:#\[\.,]*$/,
 
+       // Check if a string has a non-whitespace character in it
+       rnotwhite = /\S/,
+
+       // Used for trimming whitespace
+       rtrim = /^\s+|\s+$/g,
+
        // Keep a UserAgent string for use with jQuery.browser
        userAgent = navigator.userAgent.toLowerCase(),
 
-       // Save a reference to the core toString method
-       toString = Object.prototype.toString;
+       // Save a reference to some core methods
+       toString = Object.prototype.toString,
+       push = Array.prototype.push,
+       slice = Array.prototype.slice;
+
+// Expose jQuery to the global object
+window.jQuery = window.$ = jQuery;
 
 jQuery.fn = jQuery.prototype = {
        init: function( selector, context ) {
                var match, elem, ret;
 
                // Handle $(""), $(null), or $(undefined)
-               if ( !selector ) {
-                       this.length = 0;
-                       return this;
-               }
+               if ( !selector ) return this;
 
                // Handle $(DOMElement)
                if ( selector.nodeType ) {
-                       this[0] = selector;
-                       this.length = 1;
-                       this.context = selector;
+                       this.context = this[0] = selector;
+                       this.length++;
                        return this;
                }
 
@@ -70,17 +72,19 @@ jQuery.fn = jQuery.prototype = {
                                } else {
                                        elem = document.getElementById( match[3] );
 
-                                       // Handle the case where IE and Opera return items
-                                       // by name instead of ID
-                                       if ( elem && elem.id !== match[3] ) {
-                                               return rootjQuery.find( selector );
+                                       if ( elem ) {
+                                               // Handle the case where IE and Opera return items
+                                               // by name instead of ID
+                                               if ( elem.id !== match[3] ) return rootjQuery.find( selector );
+
+                                               // Otherwise, we inject the element directly into the jQuery object
+                                               this.length++;
+                                               this[0] = elem;
                                        }
 
-                                       // Otherwise, we inject the element directly into the jQuery object
-                                       ret = jQuery( elem || null );
-                                       ret.context = document;
-                                       ret.selector = selector;
-                                       return ret;
+                                       this.context = document;
+                                       this.selector = selector;
+                                       return this;
                                }
 
                        // HANDLE: $(expr, $(...))
@@ -116,21 +120,28 @@ jQuery.fn = jQuery.prototype = {
        // The current version of jQuery being used
        jquery: "@VERSION",
 
+       // The default length of a jQuery object is 0
+       length: 0,
+
        // The number of elements contained in the matched element set
        size: function() {
                return this.length;
        },
 
+       toArray: function(){
+               return slice.call( this, 0 );
+       },
+
        // Get the Nth element in the matched element set OR
        // Get the whole matched element set as a clean array
        get: function( num ) {
                return num == null ?
 
                        // Return a 'clean' array
-                       Array.prototype.slice.call( this ) :
+                       this.toArray() :
 
                        // Return just the object
-                       this[ num ];
+                       ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
        },
 
        // Take an array of elements and push it onto the stack
@@ -161,7 +172,7 @@ jQuery.fn = jQuery.prototype = {
                // Resetting the length to 0, then using the native Array push
                // is a super-fast way to populate an object with array-like properties
                this.length = 0;
-               Array.prototype.push.apply( this, elems );
+               push.apply( this, elems );
 
                return this;
        },
@@ -194,7 +205,7 @@ jQuery.fn = jQuery.prototype = {
 
        // For internal use only.
        // Behaves like an Array's method, not like a jQuery method.
-       push: [].push,
+       push: push,
        sort: [].sort,
        splice: [].splice
 };
@@ -240,9 +251,20 @@ jQuery.extend = jQuery.fn.extend = function() {
 
                                // Recurse if we're merging object values
                                if ( deep && copy && typeof copy === "object" && !copy.nodeType ) {
-                                       target[ name ] = jQuery.extend( deep,
-                                               // Never move original objects, clone them
-                                               src || ( copy.length != null ? [ ] : { } ), copy );
+                                       var clone;
+
+                                       if ( src ) {
+                                               clone = src;
+                                       } else if ( jQuery.isArray(copy) ) {
+                                               clone = [];
+                                       } else if ( jQuery.isObject(copy) ) {
+                                               clone = {};
+                                       } else {
+                                               clone = copy;
+                                       }
+
+                                       // Never move original objects, clone them
+                                       target[ name ] = jQuery.extend( deep, clone, copy );
 
                                // Don't bring in undefined values
                                } else if ( copy !== undefined ) {
@@ -278,21 +300,32 @@ jQuery.extend({
                return toString.call(obj) === "[object Array]";
        },
 
+       isObject: function( obj ) {
+               return this.constructor.call(obj) === Object;
+       },
+
+       isEmptyObject: function( obj ) {
+               for ( var name in obj ) {
+                       return false;
+               }
+               return true;
+       },
+
        // check if an element is in a (or is an) XML document
        isXMLDoc: function( elem ) {
-               return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
-                       !!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML";
+               return (elem.ownerDocument || elem).documentElement.nodeName !== "HTML";
        },
 
        // Evalulates a script in a global context
        globalEval: function( data ) {
-               if ( data && /\S/.test(data) ) {
+               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";
+
                        if ( jQuery.support.scriptEval ) {
                                script.appendChild( document.createTextNode( data ) );
                        } else {
@@ -312,10 +345,12 @@ jQuery.extend({
 
        // args is for internal usage only
        each: function( object, callback, args ) {
-               var name, i = 0, length = object.length;
+               var name, i = 0,
+                       length = object.length,
+                       isObj = length === undefined || jQuery.isFunction(object);
 
                if ( args ) {
-                       if ( length === undefined ) {
+                       if ( isObj ) {
                                for ( name in object ) {
                                        if ( callback.apply( object[ name ], args ) === false ) {
                                                break;
@@ -331,7 +366,7 @@ jQuery.extend({
 
                // A special, fast, case for the most common use of each
                } else {
-                       if ( length === undefined ) {
+                       if ( isObj ) {
                                for ( name in object ) {
                                        if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
                                                break;
@@ -347,7 +382,7 @@ jQuery.extend({
        },
 
        trim: function( text ) {
-               return (text || "").replace( /^\s+|\s+$/g, "" );
+               return (text || "").replace( rtrim, "" );
        },
 
        makeArray: function( array ) {
@@ -455,7 +490,7 @@ jQuery.extend({
        // It's included for backwards compatibility and plugins,
        // although they should work to migrate away.
        browser: {
-               version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
+               version: (/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/.exec(userAgent) || [0,'0'])[1],
                safari: /webkit/.test( userAgent ),
                opera: /opera/.test( userAgent ),
                msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),