X-Git-Url: http://git.asbjorn.it/?a=blobdiff_plain;ds=inline;f=src%2Fcore.js;h=ba796bca91cc652c19d07ee1b35f69c6a01411e1;hb=2a600c13efd4c6367402ae51f1e9d819585eda7d;hp=92a6bd4a8c93554d7812e9d9142ea81ef43dd2b6;hpb=6a3d1a1e281a5d13bca1ea388ae2bd8ce513ffb2;p=jquery.git diff --git a/src/core.js b/src/core.js index 92a6bd4..ba796bc 100644 --- a/src/core.js +++ b/src/core.js @@ -1,33 +1,23 @@ -/* - * jQuery @VERSION - New Wave Javascript - * - * Copyright (c) 2008 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 -var _jQuery = window.jQuery, -// Map over the $ in case of overwrite - _$ = window.$; - -var jQuery = window.jQuery = window.$ = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - return new jQuery.fn.init( selector, context ); -}; - -// A simple way to check for HTML strings or ID strings -// (both of which we optimize for) -var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/, - -// Is it a simple selector - isSimple = /^.[^:#\[\.,]*$/, +var + // Will speed up references to window, and allows munging its name. + window = this, + // Will speed up references to undefined, and allows munging its name. + undefined, + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + // Map over the $ in case of overwrite + _$ = window.$, + + jQuery = window.jQuery = window.$ = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context ); + }, -// Will speed up references to undefined, and allows munging its name. - undefined; + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/, + // Is it a simple selector + isSimple = /^.[^:#\[\.,]*$/; jQuery.fn = jQuery.prototype = { init: function( selector, context ) { @@ -57,20 +47,16 @@ jQuery.fn = jQuery.prototype = { else { var elem = document.getElementById( match[3] ); - // Make sure an element was located - if ( elem ){ - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id != match[3] ) - return jQuery().find( selector ); - - // Otherwise, we inject the element directly into the jQuery object - var ret = jQuery( elem ); - ret.context = document; - ret.selector = selector; - return ret; - } - selector = []; + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem && elem.id != match[3] ) + return jQuery().find( selector ); + + // Otherwise, we inject the element directly into the jQuery object + var ret = jQuery( elem || [] ); + ret.context = document; + ret.selector = selector; + return ret; } // HANDLE: $(expr, [context]) @@ -83,7 +69,15 @@ jQuery.fn = jQuery.prototype = { } else if ( jQuery.isFunction( selector ) ) return jQuery( document ).ready( selector ); - return this.setArray(jQuery.makeArray(selector)); + // Make sure that old selector state is passed along + if ( selector.selector && selector.context ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return this.setArray(jQuery.isArray( selector ) ? + selector : + jQuery.makeArray(selector)); }, // Start with an empty selector @@ -103,7 +97,7 @@ jQuery.fn = jQuery.prototype = { return num === undefined ? // Return a 'clean' array - jQuery.makeArray( this ) : + Array.prototype.slice.call( this ) : // Return just the object this[ num ]; @@ -210,20 +204,22 @@ jQuery.fn = jQuery.prototype = { }, wrapAll: function( html ) { - if ( this[0] ) + if ( this[0] ) { // The elements to wrap the target around - jQuery( html, this[0].ownerDocument ) - .clone() - .insertBefore( this[0] ) - .map(function(){ - var elem = this; + var wrap = jQuery( html, this[0].ownerDocument ).clone(); + + if ( this[0].parentNode ) + wrap.insertBefore( this[0] ); - while ( elem.firstChild ) - elem = elem.firstChild; + wrap.map(function(){ + var elem = this; - return elem; - }) - .append(this); + while ( elem.firstChild ) + elem = elem.firstChild; + + return elem; + }).append(this); + } return this; }, @@ -270,14 +266,23 @@ jQuery.fn = jQuery.prototype = { return this.prevObject || jQuery( [] ); }, - find: function( selector ) { - var elems = jQuery.map(this, function(elem){ - return jQuery.find( selector, elem ); - }); + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: [].push, + sort: [].sort, + splice: [].splice, - return this.pushStack( /[^+>] [^+>]/.test( selector ) ? - jQuery.unique( elems ) : - elems, "find", selector ); + find: function( selector ) { + if ( this.length === 1 ) { + var ret = this.pushStack( [], "find", selector ); + ret.length = 0; + jQuery.find( selector, this[0], ret ); + return ret; + } else { + return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){ + return jQuery.find( selector, elem ); + })), "find", selector ); + } }, clone: function( events ) { @@ -292,33 +297,37 @@ jQuery.fn = jQuery.prototype = { // attributes in IE that are actually only stored // as properties will not be copied (such as the // the name attribute on an input). - var clone = this.cloneNode(true), - container = document.createElement("div"); - container.appendChild(clone); - return jQuery.clean([container.innerHTML])[0]; + var html = this.outerHTML; + if ( !html ) { + var div = this.ownerDocument.createElement("div"); + div.appendChild( this.cloneNode(true) ); + html = div.innerHTML; + } + + return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0]; } else return this.cloneNode(true); }); - // Need to set the expando to null on the cloned set if it exists - // removeData doesn't work here, IE removes it from the original as well - // this is primarily for IE but the data expando shouldn't be copied over in any browser - var clone = ret.find("*").andSelf().each(function(){ - if ( this[ expando ] !== undefined ) - this[ expando ] = null; - }); - // Copy the events from the original to the clone - if ( events === true ) - this.find("*").andSelf().each(function(i){ - if (this.nodeType == 3) + if ( events === true ) { + var orig = this.find("*").andSelf(), i = 0; + + ret.find("*").andSelf().each(function(){ + if ( this.nodeName !== orig[i].nodeName ) return; - var events = jQuery.data( this, "events" ); - for ( var type in events ) - for ( var handler in events[ type ] ) - jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data ); + var events = jQuery.data( orig[i], "events" ); + + for ( var type in events ) { + for ( var handler in events[ type ] ) { + jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data ); + } + } + + i++; }); + } // Return the cloned set return ret; @@ -337,12 +346,18 @@ jQuery.fn = jQuery.prototype = { }, closest: function( selector ) { + var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null, + closer = 0; + return this.map(function(){ var cur = this; while ( cur && cur.ownerDocument ) { - if ( jQuery(cur).is(selector) ) + if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) { + jQuery.data(cur, "closest", closer); return cur; + } cur = cur.parentNode; + closer++; } }); }, @@ -455,7 +470,7 @@ jQuery.fn = jQuery.prototype = { html: function( value ) { return value === undefined ? (this[0] ? - this[0].innerHTML : + this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") : null) : this.empty().append( value ); }, @@ -485,15 +500,15 @@ jQuery.fn = jQuery.prototype = { domManip: function( args, table, callback ) { if ( this[0] ) { - var fragment = this[0].ownerDocument.createDocumentFragment(), - scripts = jQuery.clean( args, this[0].ownerDocument, fragment ), - first = fragment.firstChild, - extra = this.length > 1 ? fragment.cloneNode(true) : fragment; - + var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(), + scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ), + first = fragment.firstChild; + if ( first ) for ( var i = 0, l = this.length; i < l; i++ ) - callback.call( root(this[i], first), i > 0 ? extra.cloneNode(true) : fragment ); - + callback.call( root(this[i], first), this.length > 1 || i > 0 ? + fragment.cloneNode(true) : fragment ); + if ( scripts ) jQuery.each( scripts, evalScript ); } @@ -610,15 +625,13 @@ jQuery.extend({ // check if an element is in a (or is an) XML document isXMLDoc: function( elem ) { - return elem.documentElement && !elem.body || - elem.tagName && elem.ownerDocument && !elem.ownerDocument.body; + return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || + !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument ); }, // Evalulates a script in a global context globalEval: function( data ) { - data = jQuery.trim( data ); - - if ( data ) { + if ( data && /\S/.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, @@ -701,7 +714,7 @@ jQuery.extend({ // internal only, use hasClass("class") has: function( elem, className ) { - return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1; + return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1; } }, @@ -721,26 +734,32 @@ jQuery.extend({ elem.style[ name ] = old[ name ]; }, - css: function( elem, name, force ) { + css: function( elem, name, force, extra ) { if ( name == "width" || name == "height" ) { var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ]; function getWH() { val = name == "width" ? elem.offsetWidth : elem.offsetHeight; - var padding = 0, border = 0; + + if ( extra === "border" ) + return; + jQuery.each( which, function() { - padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0; - border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0; + if ( !extra ) + val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0; + if ( extra === "margin" ) + val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0; + else + val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0; }); - val -= Math.round(padding + border); } - if ( jQuery(elem).is(":visible") ) + if ( elem.offsetWidth !== 0 ) getWH(); else jQuery.swap( elem, props, getWH ); - return Math.max(0, val); + return Math.max(0, Math.round(val)); } return jQuery.curCSS( elem, name, force ); @@ -819,6 +838,14 @@ jQuery.extend({ if ( typeof context.createElement === "undefined" ) context = context.ownerDocument || context[0] && context[0].ownerDocument || document; + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) { + var match = /^<(\w+)\s*\/?>$/.exec(elems[0]); + if ( match ) + return [ context.createElement( match[1] ) ]; + } + var ret = [], scripts = [], div = context.createElement("div"); jQuery.each(elems, function(i, elem){ @@ -838,7 +865,7 @@ jQuery.extend({ }); // Trim whitespace, otherwise indexOf won't work as expected - var tags = jQuery.trim( elem ).toLowerCase(); + var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase(); var wrap = // option or optgroup @@ -878,11 +905,12 @@ jQuery.extend({ if ( !jQuery.support.tbody ) { // String was a