jQuery = window.jQuery = window.$ = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
- return new jQuery.fn.init( selector, context );
+ return selector === undefined ?
+ rootjQuery :
+ new jQuery.fn.init( selector, context );
},
// A simple way to check for HTML strings or ID strings
jQuery.fn = jQuery.prototype = {
init: function( selector, context ) {
- // Make sure that a selection was provided
- selector = selector || document;
+ // Handle $("") or $(null)
+ if ( !selector ) {
+ this.length = 0;
+ return this;
+ }
// Handle $(DOMElement)
if ( selector.nodeType ) {
this.context = selector;
return this;
}
+
// Handle HTML strings
if ( typeof selector === "string" ) {
// Are we dealing with HTML string or an ID?
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] )
- return jQuery().find( selector );
+ if ( elem && elem.id != match[3] ) {
+ return rootjQuery.find( selector );
+ }
// Otherwise, we inject the element directly into the jQuery object
- var ret = jQuery( elem || [] );
+ var ret = jQuery( elem || null );
ret.context = document;
ret.selector = selector;
return ret;
}
- // HANDLE: $(expr, [context])
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return (context || rootjQuery).find( selector );
+
+ // HANDLE: $(expr, context)
// (which is just equivalent to: $(content).find(expr)
- } else
+ } else {
return jQuery( context ).find( selector );
+ }
// HANDLE: $(function)
// Shortcut for document ready
- } else if ( jQuery.isFunction( selector ) )
- return jQuery( document ).ready( selector );
+ } else if ( jQuery.isFunction( selector ) ) {
+ return rootjQuery.ready( selector );
+ }
// Make sure that old selector state is passed along
if ( selector.selector && selector.context ) {
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
return num === undefined ?
// Return a 'clean' array
- jQuery.makeArray( this ) :
+ Array.prototype.slice.call( this ) :
// Return just the object
this[ num ];
// (returning the new matched element set)
pushStack: function( elems, name, selector ) {
// Build a new jQuery matched element set
- var ret = jQuery( elems );
+ var ret = jQuery( elems || null );
// Add the old object onto the stack (as a reference)
ret.prevObject = this;
},
end: function() {
- return this.prevObject || jQuery( [] );
+ return this.prevObject || jQuery(null);
},
- // For internal use only.
- // Behaves like an Array's .push method, not like a jQuery method.
- push: [].push,
-
find: function( selector ) {
- if ( this.length === 1 && !/,/.test(selector) ) {
- var ret = this.pushStack( [], "find", selector );
- ret.length = 0;
- jQuery.find( selector, this[0], ret );
- return ret;
- } else {
- var elems = jQuery.map(this, function(elem){
- return jQuery.find( selector, elem );
- });
-
- return this.pushStack( /[^+>] [^+>]/.test( selector ) ?
- jQuery.unique( elems ) :
- elems, "find", selector );
+ var ret = this.pushStack( "", "find", selector ), length = 0,
+ splice = Array.prototype.splice;
+
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ length = ret.length;
+ jQuery.find( selector, this[i], ret );
+
+ if ( i > 0 ) {
+ // Make sure that the results are unique
+ for ( var n = length; n < ret.length; n++ ) {
+ for ( var r = 0; r < length; r++ ) {
+ if ( ret[r] === ret[n] ) {
+ splice.call(ret, n--, 1);
+ break;
+ }
+ }
+ }
+ }
}
+
+ return ret;
},
clone: function( events ) {
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 );
}
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 );
}
});
+// All jQuery objects should point back to these
+var rootjQuery = jQuery(document);
+
// Use of jQuery.browser is deprecated.
// It's included for backwards compatibility and plugins,
// although they should work to migrate away.
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 );
};
});
},
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(){
};
});
+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;