X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=src%2Fcore.js;h=660f7eee675b311e8f8754111cb78ccbe61fa7da;hb=9029dc02a234ad9699513f81acd1423f9c2c4e30;hp=537b4e2bec7a6b250e435ad4cf97ac827d45c3a6;hpb=6728e3cf74d02794113deb0af70a5f9a7caa2241;p=jquery.git diff --git a/src/core.js b/src/core.js index 537b4e2..4da1212 100644 --- a/src/core.js +++ b/src/core.js @@ -1,1014 +1,897 @@ -/* - * jQuery @VERSION - New Wave Javascript - * - * Copyright (c) 2007 John Resig (jquery.com) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * $Date$ - * $Rev$ - */ - -// Map over jQuery in case of overwrite -if ( typeof jQuery != "undefined" ) - var _jQuery = jQuery; - -var jQuery = window.jQuery = function(a,c) { - // If the context is global, return a new object - if ( window == this || !this.init ) - return new jQuery(a,c); - - return this.init(a,c); -}; +var jQuery = (function() { -// Map over the $ in case of overwrite -if ( typeof $ != "undefined" ) - var _$ = $; - -// Map the jQuery namespace to the '$' one -window.$ = jQuery; +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context ); + }, -var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/; + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, -jQuery.fn = jQuery.prototype = { - init: function(a,c) { - // Make sure that a selection was provided - a = a || document; + // Map over the $ in case of overwrite + _$ = window.$, - // Handle HTML strings - if ( typeof a == "string" ) { - var m = quickExpr.exec(a); - if ( m && (m[1] || !c) ) { - // HANDLE: $(html) -> $(array) - if ( m[1] ) - a = jQuery.clean( [ m[1] ], c ); + // A central reference to the root jQuery(document) + rootjQuery, - // HANDLE: $("#id") - else { - var tmp = document.getElementById( m[3] ); - if ( tmp ) - // Handle the case where IE and Opera return items - // by name instead of ID - if ( tmp.id != m[3] ) - return jQuery().find( a ); - else { - this[0] = tmp; - this.length = 1; - return this; - } - else - a = []; - } + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, - // HANDLE: $(expr) - } else - return new jQuery( c ).find( a ); + // Is it a simple selector + isSimple = /^.[^:#\[\.,]*$/, - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction(a) ) - return new jQuery(document)[ jQuery.fn.ready ? "ready" : "load" ]( a ); + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + rwhite = /\s/, - return this.setArray( - // HANDLE: $(array) - a.constructor == Array && a || + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, - // HANDLE: $(arraylike) - // Watch for when an array-like object is passed as the selector - (a.jquery || a.length && a != window && !a.nodeType && a[0] != undefined && a[0].nodeType) && jQuery.makeArray( a ) || + // Check for non-word characters + rnonword = /\W/, - // HANDLE: $(*) - [ a ] ); - }, - - jquery: "@VERSION", + // Check for digits + rdigit = /\d/, - size: function() { - return this.length; - }, - - length: 0, + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, - get: function( num ) { - return num == undefined ? + // 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, - // Return a 'clean' array - jQuery.makeArray( this ) : + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, - // Return just the object - this[num]; - }, + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, - pushStack: function( a ) { - var ret = jQuery(a); - ret.prevObject = this; - return ret; - }, + // Has the ready events already been bound? + readyBound = false, - setArray: function( a ) { - this.length = 0; - Array.prototype.push.apply( this, a ); - return this; - }, + // The functions to execute on DOM ready + readyList = [], + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; - each: function( fn, args ) { - return jQuery.each( this, fn, args ); - }, +jQuery.fn = jQuery.prototype = { + init: function( selector, context ) { + var match, elem, ret, doc; - index: function( obj ) { - var pos = -1; - this.each(function(i){ - if ( this == obj ) pos = i; - }); - return pos; - }, + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } - attr: function( key, value, type ) { - var obj = key; - - // Look for the case where we're accessing a style value - if ( key.constructor == String ) - if ( value == undefined ) - return this.length && jQuery[ type || "attr" ]( this[0], key ) || undefined; - else { - obj = {}; - obj[ key ] = value; - } + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } - // Check to see if we're setting style values - return this.each(function(index){ - // Set all the styles - for ( var prop in obj ) - jQuery.attr( - type ? this.style : this, - prop, jQuery.prop(this, obj[prop], type, index, prop) - ); - }); - }, - - css: function( key, value ) { - return this.attr( key, value, "curCSS" ); - }, - - text: function(e) { - if ( typeof e != "object" && e != null ) - return this.empty().append( document.createTextNode( e ) ); - - var t = ""; - jQuery.each( e || this, function(){ - jQuery.each( this.childNodes, function(){ - if ( this.nodeType != 8 ) - t += this.nodeType != 1 ? - this.nodeValue : jQuery.fn.text([ this ]); - }); - }); - return t; - }, - - wrapAll: function(html) { - if ( this[0] ) - // The elements to wrap the target around - jQuery(html, this[0].ownerDocument) - .clone() - .insertBefore(this[0]) - .map(function(){ - var elem = this; - while ( elem.firstChild ) - elem = elem.firstChild; - return elem; - }) - .append(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; + } - return this; - }, + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + match = quickExpr.exec( selector ); - wrapInner: function(html) { - return this.each(function(){ - jQuery(this).contents().wrapAll(html); - }); - }, + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { - wrap: function(html) { - return this.each(function(){ - jQuery(this).wrapAll(html); - }); - }, + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + doc = (context ? context.ownerDocument || context : document); - append: function() { - return this.domManip(arguments, true, 1, function(a){ - this.appendChild( a ); - }); - }, + // 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 ); - prepend: function() { - return this.domManip(arguments, true, -1, function(a){ - this.insertBefore( a, this.firstChild ); - }); - }, - - before: function() { - return this.domManip(arguments, false, 1, function(a){ - this.parentNode.insertBefore( a, this ); - }); - }, + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); - after: function() { - return this.domManip(arguments, false, -1, function(a){ - this.parentNode.insertBefore( a, this.nextSibling ); - }); - }, + } else { + selector = [ doc.createElement( ret[1] ) ]; + } - end: function() { - return this.prevObject || jQuery([]); - }, + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); - find: function(t) { - var data = jQuery.map(this, function(a){ return jQuery.find(t,a); }); - return this.pushStack( /[^+>] [^+>]/.test( t ) || t.indexOf("..") > -1 ? - jQuery.unique( data ) : data ); - }, + // 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 ); + } - clone: function() { - var $this = this.add(this.find("*")); - if (jQuery.browser.msie) { - // Need to remove events on the element and its descendants - $this.each(function() { - this._$events = {}; - for (var type in this.$events) - this._$events[type] = jQuery.extend({},this.$events[type]); - }).unbind(); - } + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } - // Do the clone - var r = this.pushStack( jQuery.map( this, function(a){ - return a.cloneNode( true ); - }) ); + this.context = document; + this.selector = selector; + return this; + } - if (jQuery.browser.msie) { - $this.each(function() { - // Add the events back to the original and its descendants - var events = this._$events; - for (var type in events) - for (var handler in events[type]) - jQuery.event.add(this, type, events[type][handler], events[type][handler].data); - this._$events = null; - }); + // HANDLE: $("TAG") + } else if ( !context && !rnonword.test( selector ) ) { + this.selector = selector; + this.context = document; + selector = document.getElementsByTagName( selector ); + return jQuery.merge( this, selector ); + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return jQuery( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); } - // copy form values over - var inputs = r.add(r.find('*')).filter('select,input[@type=checkbox]'); - $this.filter('select,input[@type=checkbox]').each(function(i) { - if (this.selectedIndex) - inputs[i].selectedIndex = this.selectedIndex; - if (this.checked) - inputs[i].checked = true; - }); + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } - // Return the cloned set - return r; + return jQuery.makeArray( selector, this ); }, - filter: function(t) { - return this.pushStack( - jQuery.isFunction( t ) && - jQuery.grep(this, function(el, index){ - return t.apply(el, [index]); - }) || + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "@VERSION", + + // The default length of a jQuery object is 0 + length: 0, - jQuery.multiFilter(t,this) ); + // The number of elements contained in the matched element set + size: function() { + return this.length; }, - not: function(t) { - return this.pushStack( - t.constructor == String && - jQuery.multiFilter(t, this, true) || + 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 + this.toArray() : - jQuery.grep(this, function(a) { - return ( t.constructor == Array || t.jquery ) - ? jQuery.inArray( a, t ) < 0 - : a != t; - }) - ); + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); }, - add: function(t) { - return this.pushStack( jQuery.merge( - this.get(), - t.constructor == String ? - jQuery(t).get() : - t.length != undefined && (!t.nodeName || t.nodeName == "FORM") ? - t : [t] ) - ); + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = jQuery(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; }, - is: function(expr) { - return expr ? jQuery.multiFilter(expr,this).length > 0 : false; + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); }, - val: function( val ) { - if ( val == undefined ) { - if ( this.length ) { - var elem = this[0]; - - // We need to handle select boxes special if ( jQuery.nodeName(elem, "select") ) { var index = elem.selectedIndex, - a = [], - options = elem.options, - one = elem.type == "select-one"; - - // Nothing was selected if ( index < 0 ) - return null; - - // Loop through all the selected options for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { - var option = options[i]; if ( option.selected ) { // Get the specifc value for the option var val = jQuery.browser.msie && !option.attributes["value"].specified ? option.text : option.value; - - // We don't need an array for one selects if ( one ) - return val; - - // Multi-Selects return an array a.push(val); } } - return a; - - // Everything else, we just grab the value } else - return this[0].value.replace(/\r/g, ""); - } - } else - return this.attr( "value", val ); + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // If the DOM is already ready + if ( jQuery.isReady ) { + // Execute the function immediately + fn.call( document, jQuery ); + + // Otherwise, remember the function for later + } else if ( readyList ) { + // Add the function to the wait list + readyList.push( fn ); + } + + return this; }, - html: function( val ) { - return val == undefined ? - ( this.length ? this[0].innerHTML : null ) : - this.empty().append( val ); + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); }, - replaceWith: function( val ) { - return this.after( val ).remove(); + first: function() { + return this.eq( 0 ); }, - slice: function() { - return this.pushStack( Array.prototype.slice.apply( this, arguments ) ); + last: function() { + return this.eq( -1 ); }, - map: function(fn) { - return this.pushStack(jQuery.map( this, function(elem,i){ - return fn.call( elem, i, elem ); - })); + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); }, - andSelf: function() { - return this.add( this.prevObject ); + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); }, - domManip: function(args, table, dir, fn) { - var clone = this.length > 1, a; - - return this.each(function(){ - if ( !a ) { - a = jQuery.clean(args, this.ownerDocument); - if ( dir < 0 ) - a.reverse(); - } + end: function() { + return this.prevObject || jQuery(null); + }, - var obj = this; - - if ( table && jQuery.nodeName(this, "table") && jQuery.nodeName(a[0], "tr") ) - obj = this.getElementsByTagName("tbody")[0] || this.appendChild(document.createElement("tbody")); - - jQuery.each( a, function(){ - if ( jQuery.nodeName(this, "script") ) { - if ( this.src ) - jQuery.ajax({ url: this.src, async: false, dataType: "script" }); - else - jQuery.globalEval( this.text || this.textContent || this.innerHTML || "" ); - } else - fn.apply( obj, [ clone ? this.cloneNode(true) : this ] ); - }); - }); - } + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice }; +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + jQuery.extend = jQuery.fn.extend = function() { - // copy reference to target object - var target = arguments[0] || {}, a = 1, al = arguments.length, deep = false; + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; // Handle a deep copy situation - if ( target.constructor == Boolean ) { + if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; } // extend jQuery itself if only one argument is passed - if ( al == 1 ) { + if ( length === i ) { target = this; - a = 0; + --i; } - var prop; - - for ( ; a < al; a++ ) + for ( ; i < length; i++ ) { // Only deal with non-null/undefined values - if ( (prop = arguments[a]) != null ) + if ( (options = arguments[ i ]) != null ) { // Extend the base object - for ( var i in prop ) { + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + // Prevent never-ending loop - if ( target == prop[i] ) + if ( target === copy ) { continue; + } + + // 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 : []; - // Recurse if we're merging object values - if ( deep && typeof prop[i] == 'object' && target[i] ) - jQuery.extend( target[i], prop[i] ); + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values - else if ( prop[i] != undefined ) - target[i] = prop[i]; + } else if ( copy !== undefined ) { + target[ name ] = copy; + } } + } + } // Return the modified object return target; }; jQuery.extend({ - noConflict: function(deep) { + noConflict: function( deep ) { window.$ = _$; - if ( deep ) + + if ( deep ) { window.jQuery = _jQuery; - return jQuery; - }, + } - // This may seem like some crazy code, but trust me when I say that this - // is the only cross-browser way to do this. --John - isFunction: function( fn ) { - return !!fn && typeof fn != "string" && !fn.nodeName && - fn.constructor != Array && /function/i.test( fn + "" ); + return jQuery; }, - // check if an element is in a XML document - isXMLDoc: function(elem) { - return elem.documentElement && !elem.body || - elem.tagName && elem.ownerDocument && !elem.ownerDocument.body; - }, + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, - // Evalulates a script in a global context - // Evaluates Async. in Safari 2 :-( - globalEval: function( data ) { - data = jQuery.trim( data ); - if ( data ) { - if ( window.execScript ) - window.execScript( data ); - else if ( jQuery.browser.safari ) - // safari doesn't provide a synchronous global eval - window.setTimeout( data, 0 ); - else - eval.call( window, data ); + // 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( wait ) { + // A third-party is pushing the ready event forwards + if ( wait === true ) { + jQuery.readyWait--; } - }, - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase(); - }, + // Make sure that the DOM is not already loaded + 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, 1 ); + } - // args is for internal usage only - each: function( obj, fn, args ) { - if ( args ) { - if ( obj.length == undefined ) - for ( var i in obj ) - fn.apply( obj[i], args ); - else - for ( var i = 0, ol = obj.length; i < ol; i++ ) - if ( fn.apply( obj[i], args ) === false ) break; + // Remember that the DOM is ready + jQuery.isReady = true; - // A special, fast, case for the most common use of each - } else { - if ( obj.length == undefined ) - for ( var i in obj ) - fn.call( obj[i], i, obj[i] ); - else - for ( var i = 0, ol = obj.length, val = obj[0]; - i < ol && fn.call(val,i,val) !== false; val = obj[++i] ){} - } + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } - return obj; - }, - - prop: function(elem, value, type, index, prop){ - // Handle executable functions - if ( jQuery.isFunction( value ) ) - value = value.call( elem, [index] ); - - // exclude the following css properties to add px - var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i; - - // Handle passing in a number to a CSS property - return value && value.constructor == Number && type == "curCSS" && !exclude.test(prop) ? - value + "px" : - value; - }, - - className: { - // internal only, use addClass("class") - add: function( elem, c ){ - jQuery.each( (c || "").split(/\s+/), function(i, cur){ - if ( !jQuery.className.has( elem.className, cur ) ) - elem.className += ( elem.className ? " " : "" ) + cur; - }); - }, + // If there are functions bound, to execute + if ( readyList ) { + // Execute all of them + var fn, + i = 0, + ready = readyList; - // internal only, use removeClass("class") - remove: function( elem, c ){ - elem.className = c != undefined ? - jQuery.grep( elem.className.split(/\s+/), function(cur){ - return !jQuery.className.has( c, cur ); - }).join(" ") : ""; - }, + // Reset the list of functions + readyList = null; - // internal only, use is(".class") - has: function( t, c ) { - return jQuery.inArray( c, (t.className || t).toString().split(/\s+/) ) > -1; - } - }, + while ( (fn = ready[ i++ ]) ) { + fn.call( document, jQuery ); + } - swap: function(e,o,f) { - for ( var i in o ) { - e.style["old"+i] = e.style[i]; - e.style[i] = o[i]; + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).unbind( "ready" ); + } + } } - f.apply( e, [] ); - for ( var i in o ) - e.style[i] = e.style["old"+i]; }, + + bindReady: function() { + if ( readyBound ) { + return; + } - css: function(e,p) { - if ( p == "height" || p == "width" ) { - var old = {}, oHeight, oWidth, d = ["Top","Bottom","Right","Left"]; + readyBound = true; - jQuery.each( d, function(){ - old["padding" + this] = 0; - old["border" + this + "Width"] = 0; - }); + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } - jQuery.swap( e, old, function() { - if ( jQuery(e).is(':visible') ) { - oHeight = e.offsetHeight; - oWidth = e.offsetWidth; - } else { - e = jQuery(e.cloneNode(true)) - .find(":radio").removeAttr("checked").end() - .css({ - visibility: "hidden", position: "absolute", display: "block", right: "0", left: "0" - }).appendTo(e.parentNode)[0]; + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent("onreadystatechange", DOMContentLoaded); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); - var parPos = jQuery.css(e.parentNode,"position") || "static"; - if ( parPos == "static" ) - e.parentNode.style.position = "relative"; + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; - oHeight = e.clientHeight; - oWidth = e.clientWidth; + try { + toplevel = window.frameElement == null; + } catch(e) {} - if ( parPos == "static" ) - e.parentNode.style.position = "static"; + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, - e.parentNode.removeChild(e); - } - }); + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, - return p == "height" ? oHeight : oWidth; - } + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, - return jQuery.curCSS( e, p ); + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; }, - curCSS: function(elem, prop, force) { - var ret, stack = [], swap = []; + isNaN: function( obj ) { + return obj == null || !rdigit.test( obj ) || isNaN( obj ); + }, - // A helper method for determining if an element's values are broken - function color(a){ - if ( !jQuery.browser.safari ) - return false; + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, - var ret = document.defaultView.getComputedStyle(a,null); - return !ret || ret.getPropertyValue("color") == ""; + 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 || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; } - - if (prop == "opacity" && jQuery.browser.msie) { - ret = jQuery.attr(elem.style, "opacity"); - return ret == "" ? "1" : ret; + + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; } - if (prop.match(/float/i)) - prop = styleFloat; + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, - if (!force && elem.style[prop]) - ret = elem.style[prop]; + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } - else if (document.defaultView && document.defaultView.getComputedStyle) { + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test(data.replace(rvalidescape, "@") + .replace(rvalidtokens, "]") + .replace(rvalidbraces, "")) ) { - if (prop.match(/float/i)) - prop = "float"; + // Try to use the native JSON parser first + return window.JSON && window.JSON.parse ? + window.JSON.parse( data ) : + (new Function("return " + data))(); - prop = prop.replace(/([A-Z])/g,"-$1").toLowerCase(); - var cur = document.defaultView.getComputedStyle(elem, null); + } else { + jQuery.error( "Invalid JSON: " + data ); + } + }, - if ( cur && !color(elem) ) - ret = cur.getPropertyValue(prop); + noop: function() {}, - // If the element isn't reporting its values properly in Safari - // then some display: none elements are involved - else { - // Locate all of the parent display: none elements - for ( var a = elem; a && color(a); a = a.parentNode ) - stack.unshift(a); + // Evalulates a script in a global context + globalEval: function( 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 { + script.text = data; + } - // Go through and make them visible, but in reverse - // (It would be better if we knew the exact display type that they had) - for ( a = 0; a < stack.length; a++ ) - if ( color(stack[a]) ) { - swap[a] = stack[a].style.display; - stack[a].style.display = "block"; - } + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709). + head.insertBefore( script, head.firstChild ); + head.removeChild( script ); + } + }, - // Since we flip the display style, we have to handle that - // one special, otherwise get the value - ret = prop == "display" && swap[stack.length-1] != null ? - "none" : - document.defaultView.getComputedStyle(elem,null).getPropertyValue(prop) || ""; + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction(object); - // Finally, revert the display styles back - for ( a = 0; a < swap.length; a++ ) - if ( swap[a] != null ) - stack[a].style.display = swap[a]; + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } } - if ( prop == "opacity" && ret == "" ) - ret = "1"; - - } else if (elem.currentStyle) { - var newProp = prop.replace(/\-(\w)/g,function(m,c){return c.toUpperCase();}); - ret = elem.currentStyle[prop] || elem.currentStyle[newProp]; - - // From the awesome hack by Dean Edwards - // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 - - // If we're not dealing with a regular pixel number - // but a number that has a weird ending, we need to convert it to pixels - if ( !/^\d+(px)?$/i.test(ret) && /^\d/.test(ret) ) { - var style = elem.style.left; - var runtimeStyle = elem.runtimeStyle.left; - elem.runtimeStyle.left = elem.currentStyle.left; - elem.style.left = ret || 0; - ret = elem.style.pixelLeft + "px"; - elem.style.left = style; - elem.runtimeStyle.left = runtimeStyle; + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( var value = object[0]; + i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} } } - return ret; + return object; }, - - clean: function(a, doc) { - var r = []; - doc = doc || document; - jQuery.each( a, function(i,arg){ - if ( !arg ) return; + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : - if ( arg.constructor == Number ) - arg = arg.toString(); - - // Convert html string into DOM nodes - if ( typeof arg == "string" ) { - // Fix "XHTML"-style tags in all browsers - arg = arg.replace(/(<(\w+)[^>]*?)\/>/g, function(m, all, tag){ - return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area)$/i)? m : all+">"; - }); - - // Trim whitespace, otherwise indexOf won't work as expected - var s = jQuery.trim(arg).toLowerCase(), div = doc.createElement("div"), tb = []; - - var wrap = - // option or optgroup - !s.indexOf("", ""] || - - !s.indexOf("", ""] || - - s.match(/^<(thead|tbody|tfoot|colg|cap)/) && - [1, "", "
"] || - - !s.indexOf("", ""] || - - // matched above - (!s.indexOf("", ""] || - - !s.indexOf("", ""] || - - // IE can't serialize and