X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=src%2Fcore.js;h=a67b5f093b57ebc7f02178d00d45b2bd4a0f380d;hb=041fd5f2b52bb5c5dbb9ddbd6fffcc89fdbfe638;hp=585b200aec566b21bac9007416bc51e6aef9f2e5;hpb=28a1f022233585cf40ae727d7d8334665a495e61;p=jquery.git diff --git a/src/core.js b/src/core.js index 585b200..a67b5f0 100644 --- a/src/core.js +++ b/src/core.js @@ -22,7 +22,16 @@ var jQuery.fn = jQuery.prototype = { init: function( selector, context ) { // Make sure that a selection was provided - selector = selector || document; + if ( selector === undefined ) { + selector = document; + } + + // Handle "", null + if ( !selector ) { + this.length = 0; + this.context = document; + return this; + } // Handle $(DOMElement) if ( selector.nodeType ) { @@ -31,6 +40,7 @@ jQuery.fn = jQuery.prototype = { this.context = selector; return this; } + // Handle HTML strings if ( typeof selector === "string" ) { // Are we dealing with HTML string or an ID? @@ -40,17 +50,18 @@ jQuery.fn = jQuery.prototype = { if ( match && (match[1] || !context) ) { // HANDLE: $(html) -> $(array) - if ( match[1] ) + if ( match[1] ) { selector = jQuery.clean( [ match[1] ], context ); // HANDLE: $("#id") - else { + } else { var 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] ) + if ( elem && elem.id != match[3] ) { return jQuery().find( selector ); + } // Otherwise, we inject the element directly into the jQuery object var ret = jQuery( elem || [] ); @@ -61,13 +72,21 @@ jQuery.fn = jQuery.prototype = { // HANDLE: $(expr, [context]) // (which is just equivalent to: $(content).find(expr) - } else - return jQuery( context ).find( selector ); + } else if ( !context || context.nodeType ) { + this[0] = context || document; + this.length = 1; + this.context = context; + return this.find( selector ); + + } else { + return (context.jquery ? context : jQuery( context )).find( selector ); + } // HANDLE: $(function) // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) + } else if ( jQuery.isFunction( selector ) ) { return jQuery( document ).ready( selector ); + } // Make sure that old selector state is passed along if ( selector.selector && selector.context ) { @@ -75,7 +94,9 @@ jQuery.fn = jQuery.prototype = { this.context = selector.context; } - return this.setArray(jQuery.makeArray(selector)); + return this.setArray(jQuery.isArray( selector ) ? + selector : + jQuery.makeArray(selector)); }, // Start with an empty selector @@ -95,7 +116,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 ]; @@ -265,23 +286,20 @@ jQuery.fn = jQuery.prototype = { }, // For internal use only. - // Behaves like an Array's .push method, not like a jQuery method. + // Behaves like an Array's method, not like a jQuery method. push: [].push, + sort: [].sort, + splice: [].splice, find: function( selector ) { - if ( this.length === 1 && !/,/.test(selector) ) { - var ret = this.pushStack( [], "find", selector ); - ret.length = 0; + if ( this.length === 1 ) { + var ret = this.pushStack( "", "find", selector ); jQuery.find( selector, this[0], ret ); return ret; } else { - var elems = jQuery.map(this, function(elem){ + return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){ return jQuery.find( selector, elem ); - }); - - return this.pushStack( /[^+>] [^+>]/.test( selector ) ? - jQuery.unique( elems ) : - elems, "find", selector ); + })), "find", selector ); } }, @@ -297,33 +315,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; @@ -342,14 +364,18 @@ jQuery.fn = jQuery.prototype = { }, closest: function( selector ) { - var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null; + 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 ( pos ? pos.index(cur) > -1 : 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++; } }); }, @@ -462,7 +488,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 ); }, @@ -494,13 +520,13 @@ jQuery.fn = jQuery.prototype = { if ( this[0] ) { var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(), scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ), - first = fragment.firstChild, - extra = this.length > 1 ? fragment.cloneNode(true) : 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 ); } @@ -623,9 +649,7 @@ jQuery.extend({ // 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, @@ -708,7 +732,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; } }, @@ -728,26 +752,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 ); @@ -853,7 +883,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 @@ -893,11 +923,12 @@ jQuery.extend({ if ( !jQuery.support.tbody ) { // String was a , *may* have spurious - var tbody = !tags.indexOf(" or - wrap[1] == "
" && tags.indexOf("" && !hasBody ? div.childNodes : []; @@ -1176,13 +1207,16 @@ jQuery.each({ insertAfter: "after", replaceAll: "replaceWith" }, function(name, original){ - jQuery.fn[ name ] = function() { - var args = arguments; + jQuery.fn[ name ] = function( selector ) { + var ret = [], insert = jQuery( selector ); - return this.each(function(){ - for ( var i = 0, length = args.length; i < length; i++ ) - jQuery( args[ i ] )[ original ]( this ); - }); + for ( var i = 0, l = insert.length; i < l; i++ ) { + var elems = (i > 0 ? this.clone(true) : this).get(); + jQuery.fn[ original ].apply( jQuery(insert[i]), elems ); + ret = ret.concat( elems ); + } + + return this.pushStack( ret, name, selector ); }; }); @@ -1208,24 +1242,28 @@ jQuery.each({ }, remove: function( selector ) { - if ( !selector || jQuery.filter( selector, [ this ] ).length ) { - // Prevent memory leaks - jQuery( "*", this ).add([this]).each(function(){ - jQuery.event.remove(this); - jQuery.removeData(this); - }); - if (this.parentNode) + if ( !selector || jQuery.multiFilter( selector, [ this ] ).length ) { + if ( this.nodeType === 1 ) { + cleanData( this.getElementsByTagName("*") ); + cleanData( [this] ); + } + + if ( this.parentNode ) { this.parentNode.removeChild( this ); + } } }, empty: function() { // Remove element nodes and prevent memory leaks - jQuery( ">*", this ).remove(); + if ( this.nodeType === 1 ) { + cleanData( this.getElementsByTagName("*") ); + } // Remove any remaining nodes - while ( this.firstChild ) + while ( this.firstChild ) { this.removeChild( this.firstChild ); + } } }, function(name, fn){ jQuery.fn[ name ] = function(){ @@ -1233,6 +1271,15 @@ jQuery.each({ }; }); +function cleanData( elems ) { + for ( var i = 0, l = elems.length; i < l; i++ ) { + var id = elems[i][expando]; + if ( id ) { + delete jQuery.cache[ id ]; + } + } +} + // Helper function used by the dimensions and offset modules function num(elem, prop) { return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;