Landing pull request 586. Create exports.js for exporting jQuery to window and AMD...
[jquery.git] / src / core.js
blobe56394bf65aef4ae003f89560f9274bcd1e94964
1 var jQuery = (function() {
3 // Define a local copy of jQuery
4 var jQuery = function( selector, context ) {
5                 // The jQuery object is actually just the init constructor 'enhanced'
6                 return new jQuery.fn.init( selector, context, rootjQuery );
7         },
9         // Map over jQuery in case of overwrite
10         _jQuery = window.jQuery,
12         // Map over the $ in case of overwrite
13         _$ = window.$,
15         // A central reference to the root jQuery(document)
16         rootjQuery,
18         // A simple way to check for HTML strings or ID strings
19         // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
20         quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
22         // Check if a string has a non-whitespace character in it
23         rnotwhite = /\S/,
25         // Used for trimming whitespace
26         trimLeft = /^\s+/,
27         trimRight = /\s+$/,
29         // Check for digits
30         rdigit = /\d/,
32         // Match a standalone tag
33         rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
35         // JSON RegExp
36         rvalidchars = /^[\],:{}\s]*$/,
37         rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
38         rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
39         rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
41         // Useragent RegExp
42         rwebkit = /(webkit)[ \/]([\w.]+)/,
43         ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
44         rmsie = /(msie) ([\w.]+)/,
45         rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
47         // Matches dashed string for camelizing
48         rdashAlpha = /-([a-z]|[0-9])/ig,
49         rmsPrefix = /^-ms-/,
51         // Used by jQuery.camelCase as callback to replace()
52         fcamelCase = function( all, letter ) {
53                 return ( letter + "" ).toUpperCase();
54         },
56         // Keep a UserAgent string for use with jQuery.browser
57         userAgent = navigator.userAgent,
59         // For matching the engine and version of the browser
60         browserMatch,
62         // The deferred used on DOM ready
63         readyList,
65         // The ready event handler
66         DOMContentLoaded,
68         // Save a reference to some core methods
69         toString = Object.prototype.toString,
70         hasOwn = Object.prototype.hasOwnProperty,
71         push = Array.prototype.push,
72         slice = Array.prototype.slice,
73         trim = String.prototype.trim,
74         indexOf = Array.prototype.indexOf,
76         // [[Class]] -> type pairs
77         class2type = {};
79 jQuery.fn = jQuery.prototype = {
80         constructor: jQuery,
81         init: function( selector, context, rootjQuery ) {
82                 var match, elem, ret, doc;
84                 // Handle $(""), $(null), or $(undefined)
85                 if ( !selector ) {
86                         return this;
87                 }
89                 // Handle $(DOMElement)
90                 if ( selector.nodeType ) {
91                         this.context = this[0] = selector;
92                         this.length = 1;
93                         return this;
94                 }
96                 // The body element only exists once, optimize finding it
97                 if ( selector === "body" && !context && document.body ) {
98                         this.context = document;
99                         this[0] = document.body;
100                         this.selector = selector;
101                         this.length = 1;
102                         return this;
103                 }
105                 // Handle HTML strings
106                 if ( typeof selector === "string" ) {
107                         // Are we dealing with HTML string or an ID?
108                         if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
109                                 // Assume that strings that start and end with <> are HTML and skip the regex check
110                                 match = [ null, selector, null ];
112                         } else {
113                                 match = quickExpr.exec( selector );
114                         }
116                         // Verify a match, and that no context was specified for #id
117                         if ( match && (match[1] || !context) ) {
119                                 // HANDLE: $(html) -> $(array)
120                                 if ( match[1] ) {
121                                         context = context instanceof jQuery ? context[0] : context;
122                                         doc = ( context ? context.ownerDocument || context : document );
124                                         // If a single string is passed in and it's a single tag
125                                         // just do a createElement and skip the rest
126                                         ret = rsingleTag.exec( selector );
128                                         if ( ret ) {
129                                                 if ( jQuery.isPlainObject( context ) ) {
130                                                         selector = [ document.createElement( ret[1] ) ];
131                                                         jQuery.fn.attr.call( selector, context, true );
133                                                 } else {
134                                                         selector = [ doc.createElement( ret[1] ) ];
135                                                 }
137                                         } else {
138                                                 ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
139                                                 selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
140                                         }
142                                         return jQuery.merge( this, selector );
144                                 // HANDLE: $("#id")
145                                 } else {
146                                         elem = document.getElementById( match[2] );
148                                         // Check parentNode to catch when Blackberry 4.6 returns
149                                         // nodes that are no longer in the document #6963
150                                         if ( elem && elem.parentNode ) {
151                                                 // Handle the case where IE and Opera return items
152                                                 // by name instead of ID
153                                                 if ( elem.id !== match[2] ) {
154                                                         return rootjQuery.find( selector );
155                                                 }
157                                                 // Otherwise, we inject the element directly into the jQuery object
158                                                 this.length = 1;
159                                                 this[0] = elem;
160                                         }
162                                         this.context = document;
163                                         this.selector = selector;
164                                         return this;
165                                 }
167                         // HANDLE: $(expr, $(...))
168                         } else if ( !context || context.jquery ) {
169                                 return ( context || rootjQuery ).find( selector );
171                         // HANDLE: $(expr, context)
172                         // (which is just equivalent to: $(context).find(expr)
173                         } else {
174                                 return this.constructor( context ).find( selector );
175                         }
177                 // HANDLE: $(function)
178                 // Shortcut for document ready
179                 } else if ( jQuery.isFunction( selector ) ) {
180                         return rootjQuery.ready( selector );
181                 }
183                 if ( selector.selector !== undefined ) {
184                         this.selector = selector.selector;
185                         this.context = selector.context;
186                 }
188                 return jQuery.makeArray( selector, this );
189         },
191         // Start with an empty selector
192         selector: "",
194         // The current version of jQuery being used
195         jquery: "@VERSION",
197         // The default length of a jQuery object is 0
198         length: 0,
200         // The number of elements contained in the matched element set
201         size: function() {
202                 return this.length;
203         },
205         toArray: function() {
206                 return slice.call( this, 0 );
207         },
209         // Get the Nth element in the matched element set OR
210         // Get the whole matched element set as a clean array
211         get: function( num ) {
212                 return num == null ?
214                         // Return a 'clean' array
215                         this.toArray() :
217                         // Return just the object
218                         ( num < 0 ? this[ this.length + num ] : this[ num ] );
219         },
221         // Take an array of elements and push it onto the stack
222         // (returning the new matched element set)
223         pushStack: function( elems, name, selector ) {
224                 // Build a new jQuery matched element set
225                 var ret = this.constructor();
227                 if ( jQuery.isArray( elems ) ) {
228                         push.apply( ret, elems );
230                 } else {
231                         jQuery.merge( ret, elems );
232                 }
234                 // Add the old object onto the stack (as a reference)
235                 ret.prevObject = this;
237                 ret.context = this.context;
239                 if ( name === "find" ) {
240                         ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
241                 } else if ( name ) {
242                         ret.selector = this.selector + "." + name + "(" + selector + ")";
243                 }
245                 // Return the newly-formed element set
246                 return ret;
247         },
249         // Execute a callback for every element in the matched set.
250         // (You can seed the arguments with an array of args, but this is
251         // only used internally.)
252         each: function( callback, args ) {
253                 return jQuery.each( this, callback, args );
254         },
256         ready: function( fn ) {
257                 // Attach the listeners
258                 jQuery.bindReady();
260                 // Add the callback
261                 readyList.add( fn );
263                 return this;
264         },
266         eq: function( i ) {
267                 i = +i;
268                 return i === -1 ?
269                         this.slice( i ) :
270                         this.slice( i, i + 1 );
271         },
273         first: function() {
274                 return this.eq( 0 );
275         },
277         last: function() {
278                 return this.eq( -1 );
279         },
281         slice: function() {
282                 return this.pushStack( slice.apply( this, arguments ),
283                         "slice", slice.call(arguments).join(",") );
284         },
286         map: function( callback ) {
287                 return this.pushStack( jQuery.map(this, function( elem, i ) {
288                         return callback.call( elem, i, elem );
289                 }));
290         },
292         end: function() {
293                 return this.prevObject || this.constructor(null);
294         },
296         // For internal use only.
297         // Behaves like an Array's method, not like a jQuery method.
298         push: push,
299         sort: [].sort,
300         splice: [].splice
303 // Give the init function the jQuery prototype for later instantiation
304 jQuery.fn.init.prototype = jQuery.fn;
306 jQuery.extend = jQuery.fn.extend = function() {
307         var options, name, src, copy, copyIsArray, clone,
308                 target = arguments[0] || {},
309                 i = 1,
310                 length = arguments.length,
311                 deep = false;
313         // Handle a deep copy situation
314         if ( typeof target === "boolean" ) {
315                 deep = target;
316                 target = arguments[1] || {};
317                 // skip the boolean and the target
318                 i = 2;
319         }
321         // Handle case when target is a string or something (possible in deep copy)
322         if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
323                 target = {};
324         }
326         // extend jQuery itself if only one argument is passed
327         if ( length === i ) {
328                 target = this;
329                 --i;
330         }
332         for ( ; i < length; i++ ) {
333                 // Only deal with non-null/undefined values
334                 if ( (options = arguments[ i ]) != null ) {
335                         // Extend the base object
336                         for ( name in options ) {
337                                 src = target[ name ];
338                                 copy = options[ name ];
340                                 // Prevent never-ending loop
341                                 if ( target === copy ) {
342                                         continue;
343                                 }
345                                 // Recurse if we're merging plain objects or arrays
346                                 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
347                                         if ( copyIsArray ) {
348                                                 copyIsArray = false;
349                                                 clone = src && jQuery.isArray(src) ? src : [];
351                                         } else {
352                                                 clone = src && jQuery.isPlainObject(src) ? src : {};
353                                         }
355                                         // Never move original objects, clone them
356                                         target[ name ] = jQuery.extend( deep, clone, copy );
358                                 // Don't bring in undefined values
359                                 } else if ( copy !== undefined ) {
360                                         target[ name ] = copy;
361                                 }
362                         }
363                 }
364         }
366         // Return the modified object
367         return target;
370 jQuery.extend({
371         noConflict: function( deep ) {
372                 if ( window.$ === jQuery ) {
373                         window.$ = _$;
374                 }
376                 if ( deep && window.jQuery === jQuery ) {
377                         window.jQuery = _jQuery;
378                 }
380                 return jQuery;
381         },
383         // Is the DOM ready to be used? Set to true once it occurs.
384         isReady: false,
386         // A counter to track how many items to wait for before
387         // the ready event fires. See #6781
388         readyWait: 1,
390         // Hold (or release) the ready event
391         holdReady: function( hold ) {
392                 if ( hold ) {
393                         jQuery.readyWait++;
394                 } else {
395                         jQuery.ready( true );
396                 }
397         },
399         // Handle when the DOM is ready
400         ready: function( wait ) {
401                 // Either a released hold or an DOMready/load event and not yet ready
402                 if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
403                         // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
404                         if ( !document.body ) {
405                                 return setTimeout( jQuery.ready, 1 );
406                         }
408                         // Remember that the DOM is ready
409                         jQuery.isReady = true;
411                         // If a normal DOM Ready event fired, decrement, and wait if need be
412                         if ( wait !== true && --jQuery.readyWait > 0 ) {
413                                 return;
414                         }
416                         // If there are functions bound, to execute
417                         readyList.fireWith( document, [ jQuery ] );
419                         // Trigger any bound ready events
420                         if ( jQuery.fn.trigger ) {
421                                 jQuery( document ).trigger( "ready" ).off( "ready" );
422                         }
423                 }
424         },
426         bindReady: function() {
427                 if ( readyList ) {
428                         return;
429                 }
431                 readyList = jQuery.Callbacks( "once memory" );
433                 // Catch cases where $(document).ready() is called after the
434                 // browser event has already occurred.
435                 if ( document.readyState === "complete" ) {
436                         // Handle it asynchronously to allow scripts the opportunity to delay ready
437                         return setTimeout( jQuery.ready, 1 );
438                 }
440                 // Mozilla, Opera and webkit nightlies currently support this event
441                 if ( document.addEventListener ) {
442                         // Use the handy event callback
443                         document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
445                         // A fallback to window.onload, that will always work
446                         window.addEventListener( "load", jQuery.ready, false );
448                 // If IE event model is used
449                 } else if ( document.attachEvent ) {
450                         // ensure firing before onload,
451                         // maybe late but safe also for iframes
452                         document.attachEvent( "onreadystatechange", DOMContentLoaded );
454                         // A fallback to window.onload, that will always work
455                         window.attachEvent( "onload", jQuery.ready );
457                         // If IE and not a frame
458                         // continually check to see if the document is ready
459                         var toplevel = false;
461                         try {
462                                 toplevel = window.frameElement == null;
463                         } catch(e) {}
465                         if ( document.documentElement.doScroll && toplevel ) {
466                                 doScrollCheck();
467                         }
468                 }
469         },
471         // See test/unit/core.js for details concerning isFunction.
472         // Since version 1.3, DOM methods and functions like alert
473         // aren't supported. They return false on IE (#2968).
474         isFunction: function( obj ) {
475                 return jQuery.type(obj) === "function";
476         },
478         isArray: Array.isArray || function( obj ) {
479                 return jQuery.type(obj) === "array";
480         },
482         // A crude way of determining if an object is a window
483         isWindow: function( obj ) {
484                 return obj && typeof obj === "object" && "setInterval" in obj;
485         },
487         isNumeric: function( obj ) {
488                 return !isNaN( parseFloat(obj) ) && isFinite( obj );
489         },
491         type: function( obj ) {
492                 return obj == null ?
493                         String( obj ) :
494                         class2type[ toString.call(obj) ] || "object";
495         },
497         isPlainObject: function( obj ) {
498                 // Must be an Object.
499                 // Because of IE, we also have to check the presence of the constructor property.
500                 // Make sure that DOM nodes and window objects don't pass through, as well
501                 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
502                         return false;
503                 }
505                 try {
506                         // Not own constructor property must be Object
507                         if ( obj.constructor &&
508                                 !hasOwn.call(obj, "constructor") &&
509                                 !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
510                                 return false;
511                         }
512                 } catch ( e ) {
513                         // IE8,9 Will throw exceptions on certain host objects #9897
514                         return false;
515                 }
517                 // Own properties are enumerated firstly, so to speed up,
518                 // if last one is own, then all properties are own.
520                 var key;
521                 for ( key in obj ) {}
523                 return key === undefined || hasOwn.call( obj, key );
524         },
526         isEmptyObject: function( obj ) {
527                 for ( var name in obj ) {
528                         return false;
529                 }
530                 return true;
531         },
533         error: function( msg ) {
534                 throw new Error( msg );
535         },
537         parseJSON: function( data ) {
538                 if ( typeof data !== "string" || !data ) {
539                         return null;
540                 }
542                 // Make sure leading/trailing whitespace is removed (IE can't handle it)
543                 data = jQuery.trim( data );
545                 // Attempt to parse using the native JSON parser first
546                 if ( window.JSON && window.JSON.parse ) {
547                         return window.JSON.parse( data );
548                 }
550                 // Make sure the incoming data is actual JSON
551                 // Logic borrowed from http://json.org/json2.js
552                 if ( rvalidchars.test( data.replace( rvalidescape, "@" )
553                         .replace( rvalidtokens, "]" )
554                         .replace( rvalidbraces, "")) ) {
556                         return ( new Function( "return " + data ) )();
558                 }
559                 jQuery.error( "Invalid JSON: " + data );
560         },
562         // Cross-browser xml parsing
563         parseXML: function( data ) {
564                 var xml, tmp;
565                 try {
566                         if ( window.DOMParser ) { // Standard
567                                 tmp = new DOMParser();
568                                 xml = tmp.parseFromString( data , "text/xml" );
569                         } else { // IE
570                                 xml = new ActiveXObject( "Microsoft.XMLDOM" );
571                                 xml.async = "false";
572                                 xml.loadXML( data );
573                         }
574                 } catch( e ) {
575                         xml = undefined;
576                 }
577                 if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
578                         jQuery.error( "Invalid XML: " + data );
579                 }
580                 return xml;
581         },
583         noop: function() {},
585         // Evaluates a script in a global context
586         // Workarounds based on findings by Jim Driscoll
587         // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
588         globalEval: function( data ) {
589                 if ( data && rnotwhite.test( data ) ) {
590                         // We use execScript on Internet Explorer
591                         // We use an anonymous function so that context is window
592                         // rather than jQuery in Firefox
593                         ( window.execScript || function( data ) {
594                                 window[ "eval" ].call( window, data );
595                         } )( data );
596                 }
597         },
599         // Convert dashed to camelCase; used by the css and data modules
600         // Microsoft forgot to hump their vendor prefix (#9572)
601         camelCase: function( string ) {
602                 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
603         },
605         nodeName: function( elem, name ) {
606                 return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
607         },
609         // args is for internal usage only
610         each: function( object, callback, args ) {
611                 var name, i = 0,
612                         length = object.length,
613                         isObj = length === undefined || jQuery.isFunction( object );
615                 if ( args ) {
616                         if ( isObj ) {
617                                 for ( name in object ) {
618                                         if ( callback.apply( object[ name ], args ) === false ) {
619                                                 break;
620                                         }
621                                 }
622                         } else {
623                                 for ( ; i < length; ) {
624                                         if ( callback.apply( object[ i++ ], args ) === false ) {
625                                                 break;
626                                         }
627                                 }
628                         }
630                 // A special, fast, case for the most common use of each
631                 } else {
632                         if ( isObj ) {
633                                 for ( name in object ) {
634                                         if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
635                                                 break;
636                                         }
637                                 }
638                         } else {
639                                 for ( ; i < length; ) {
640                                         if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
641                                                 break;
642                                         }
643                                 }
644                         }
645                 }
647                 return object;
648         },
650         // Use native String.trim function wherever possible
651         trim: trim ?
652                 function( text ) {
653                         return text == null ?
654                                 "" :
655                                 trim.call( text );
656                 } :
658                 // Otherwise use our own trimming functionality
659                 function( text ) {
660                         return text == null ?
661                                 "" :
662                                 text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
663                 },
665         // results is for internal usage only
666         makeArray: function( array, results ) {
667                 var ret = results || [];
669                 if ( array != null ) {
670                         // The window, strings (and functions) also have 'length'
671                         // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
672                         var type = jQuery.type( array );
674                         if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
675                                 push.call( ret, array );
676                         } else {
677                                 jQuery.merge( ret, array );
678                         }
679                 }
681                 return ret;
682         },
684         inArray: function( elem, array, i ) {
685                 var len;
687                 if ( array ) {
688                         if ( indexOf ) {
689                                 return indexOf.call( array, elem, i );
690                         }
692                         len = array.length;
693                         i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
695                         for ( ; i < len; i++ ) {
696                                 // Skip accessing in sparse arrays
697                                 if ( i in array && array[ i ] === elem ) {
698                                         return i;
699                                 }
700                         }
701                 }
703                 return -1;
704         },
706         merge: function( first, second ) {
707                 var i = first.length,
708                         j = 0;
710                 if ( typeof second.length === "number" ) {
711                         for ( var l = second.length; j < l; j++ ) {
712                                 first[ i++ ] = second[ j ];
713                         }
715                 } else {
716                         while ( second[j] !== undefined ) {
717                                 first[ i++ ] = second[ j++ ];
718                         }
719                 }
721                 first.length = i;
723                 return first;
724         },
726         grep: function( elems, callback, inv ) {
727                 var ret = [], retVal;
728                 inv = !!inv;
730                 // Go through the array, only saving the items
731                 // that pass the validator function
732                 for ( var i = 0, length = elems.length; i < length; i++ ) {
733                         retVal = !!callback( elems[ i ], i );
734                         if ( inv !== retVal ) {
735                                 ret.push( elems[ i ] );
736                         }
737                 }
739                 return ret;
740         },
742         // arg is for internal usage only
743         map: function( elems, callback, arg ) {
744                 var value, key, ret = [],
745                         i = 0,
746                         length = elems.length,
747                         // jquery objects are treated as arrays
748                         isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
750                 // Go through the array, translating each of the items to their
751                 if ( isArray ) {
752                         for ( ; i < length; i++ ) {
753                                 value = callback( elems[ i ], i, arg );
755                                 if ( value != null ) {
756                                         ret[ ret.length ] = value;
757                                 }
758                         }
760                 // Go through every key on the object,
761                 } else {
762                         for ( key in elems ) {
763                                 value = callback( elems[ key ], key, arg );
765                                 if ( value != null ) {
766                                         ret[ ret.length ] = value;
767                                 }
768                         }
769                 }
771                 // Flatten any nested arrays
772                 return ret.concat.apply( [], ret );
773         },
775         // A global GUID counter for objects
776         guid: 1,
778         // Bind a function to a context, optionally partially applying any
779         // arguments.
780         proxy: function( fn, context ) {
781                 if ( typeof context === "string" ) {
782                         var tmp = fn[ context ];
783                         context = fn;
784                         fn = tmp;
785                 }
787                 // Quick check to determine if target is callable, in the spec
788                 // this throws a TypeError, but we will just return undefined.
789                 if ( !jQuery.isFunction( fn ) ) {
790                         return undefined;
791                 }
793                 // Simulated bind
794                 var args = slice.call( arguments, 2 ),
795                         proxy = function() {
796                                 return fn.apply( context, args.concat( slice.call( arguments ) ) );
797                         };
799                 // Set the guid of unique handler to the same of original handler, so it can be removed
800                 proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
802                 return proxy;
803         },
805         // Mutifunctional method to get and set values to a collection
806         // The value/s can optionally be executed if it's a function
807         access: function( elems, key, value, exec, fn, pass ) {
808                 var length = elems.length;
810                 // Setting many attributes
811                 if ( typeof key === "object" ) {
812                         for ( var k in key ) {
813                                 jQuery.access( elems, k, key[k], exec, fn, value );
814                         }
815                         return elems;
816                 }
818                 // Setting one attribute
819                 if ( value !== undefined ) {
820                         // Optionally, function values get executed if exec is true
821                         exec = !pass && exec && jQuery.isFunction(value);
823                         for ( var i = 0; i < length; i++ ) {
824                                 fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
825                         }
827                         return elems;
828                 }
830                 // Getting an attribute
831                 return length ? fn( elems[0], key ) : undefined;
832         },
834         now: function() {
835                 return ( new Date() ).getTime();
836         },
838         // Use of jQuery.browser is frowned upon.
839         // More details: http://docs.jquery.com/Utilities/jQuery.browser
840         uaMatch: function( ua ) {
841                 ua = ua.toLowerCase();
843                 var match = rwebkit.exec( ua ) ||
844                         ropera.exec( ua ) ||
845                         rmsie.exec( ua ) ||
846                         ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
847                         [];
849                 return { browser: match[1] || "", version: match[2] || "0" };
850         },
852         sub: function() {
853                 function jQuerySub( selector, context ) {
854                         return new jQuerySub.fn.init( selector, context );
855                 }
856                 jQuery.extend( true, jQuerySub, this );
857                 jQuerySub.superclass = this;
858                 jQuerySub.fn = jQuerySub.prototype = this();
859                 jQuerySub.fn.constructor = jQuerySub;
860                 jQuerySub.sub = this.sub;
861                 jQuerySub.fn.init = function init( selector, context ) {
862                         if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
863                                 context = jQuerySub( context );
864                         }
866                         return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
867                 };
868                 jQuerySub.fn.init.prototype = jQuerySub.fn;
869                 var rootjQuerySub = jQuerySub(document);
870                 return jQuerySub;
871         },
873         browser: {}
876 // Populate the class2type map
877 jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
878         class2type[ "[object " + name + "]" ] = name.toLowerCase();
881 browserMatch = jQuery.uaMatch( userAgent );
882 if ( browserMatch.browser ) {
883         jQuery.browser[ browserMatch.browser ] = true;
884         jQuery.browser.version = browserMatch.version;
887 // Deprecated, use jQuery.browser.webkit instead
888 if ( jQuery.browser.webkit ) {
889         jQuery.browser.safari = true;
892 // IE doesn't match non-breaking spaces with \s
893 if ( rnotwhite.test( "\xA0" ) ) {
894         trimLeft = /^[\s\xA0]+/;
895         trimRight = /[\s\xA0]+$/;
898 // All jQuery objects should point back to these
899 rootjQuery = jQuery(document);
901 // Cleanup functions for the document ready method
902 if ( document.addEventListener ) {
903         DOMContentLoaded = function() {
904                 document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
905                 jQuery.ready();
906         };
908 } else if ( document.attachEvent ) {
909         DOMContentLoaded = function() {
910                 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
911                 if ( document.readyState === "complete" ) {
912                         document.detachEvent( "onreadystatechange", DOMContentLoaded );
913                         jQuery.ready();
914                 }
915         };
918 // The DOM ready check for Internet Explorer
919 function doScrollCheck() {
920         if ( jQuery.isReady ) {
921                 return;
922         }
924         try {
925                 // If IE is used, use the trick by Diego Perini
926                 // http://javascript.nwbox.com/IEContentLoaded/
927                 document.documentElement.doScroll("left");
928         } catch(e) {
929                 setTimeout( doScrollCheck, 1 );
930                 return;
931         }
933         // and execute any waiting functions
934         jQuery.ready();
937 return jQuery;
939 })();