fix for #3688, setting type attribute on button causes IE to throw error
[jquery.git] / src / core.js
index 7ddb2c5..271e7c4 100644 (file)
@@ -1,38 +1,33 @@
-/*
- * 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 selector === undefined ?
+                       rootjQuery :
+                       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 ) {
-               // 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 ) {
@@ -41,6 +36,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?
@@ -50,40 +46,51 @@ 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] );
 
-                                       // 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;
+                                       // Handle the case where IE and Opera return items
+                                       // by name instead of ID
+                                       if ( elem && elem.id != match[3] ) {
+                                               return rootjQuery.find( selector );
                                        }
-                                       selector = [];
+
+                                       // Otherwise, we inject the element directly into the jQuery object
+                                       var ret = jQuery( elem || null );
+                                       ret.context = document;
+                                       ret.selector = selector;
+                                       return ret;
                                }
 
-                       // HANDLE: $(expr, [context])
-                       // (which is just equivalent to: $(content).find(expr)
-                       } else
+                       // 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 jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( 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.selector = selector.selector;
+                       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
@@ -103,7 +110,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 ];
@@ -113,7 +120,7 @@ jQuery.fn = jQuery.prototype = {
        // (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;
@@ -151,8 +158,6 @@ jQuery.fn = jQuery.prototype = {
        // Determine the position of an element within
        // the matched set of elements
        index: function( elem ) {
-               var ret = -1;
-
                // Locate the position of the desired element
                return jQuery.inArray(
                        // If it receives a jQuery object, the first element is used
@@ -161,29 +166,42 @@ jQuery.fn = jQuery.prototype = {
        },
 
        attr: function( name, value, type ) {
-               var options = name;
+               var options = name, isFunction = jQuery.isFunction( value );
 
                // Look for the case where we're accessing a style value
-               if ( typeof name === "string" )
-                       if ( value === undefined )
-                               return this[0] && jQuery[ type || "attr" ]( this[0], name );
+               if ( typeof name === "string" ) {
+                       if ( value === undefined ) {
+                               return this.length ?
+                                       jQuery[ type || "attr" ]( this[0], name ) :
+                                       null;
 
-                       else {
+                       } else {
                                options = {};
                                options[ name ] = value;
                        }
+               }
 
                // Check to see if we're setting style values
-               return this.each(function(i){
+               for ( var i = 0, l = this.length; i < l; i++ ) {
+                       var elem = this[i];
+
                        // Set all the styles
-                       for ( name in options )
-                               jQuery.attr(
-                                       type ?
-                                               this.style :
-                                               this,
-                                       name, jQuery.prop( this, options[ name ], type, i, name )
-                               );
-               });
+                       for ( var prop in options ) {
+                               value = options[prop];
+
+                               if ( isFunction ) {
+                                       value = value.call( elem, i );
+                               }
+
+                               if ( typeof value === "number" && type === "curCSS" && !exclude.test(prop) ) {
+                                       value = value + "px";
+                               }
+
+                               jQuery.attr( type ? elem.style : elem, prop, value );
+                       }
+               }
+
+               return this;
        },
 
        css: function( key, value ) {
@@ -212,20 +230,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;
        },
@@ -269,17 +289,36 @@ jQuery.fn = jQuery.prototype = {
        },
 
        end: function() {
-               return this.prevObject || jQuery( [] );
+               return this.prevObject || jQuery(null);
        },
 
+       // For internal use only.
+       // Behaves like an Array's method, not like a jQuery method.
+       push: [].push,
+       sort: [].sort,
+       splice: [].splice,
+
        find: function( selector ) {
-               var elems = jQuery.map(this, function(elem){
-                       return jQuery.find( selector, elem );
-               });
+               var ret = this.pushStack( "", "find", selector ), length = 0;
+
+               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] ) {
+                                                       ret.splice(n--, 1);
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+               }
 
-               return this.pushStack( /[^+>] [^+>]/.test( selector ) ?
-                       jQuery.unique( elems ) :
-                       elems, "find", selector );
+               return ret;
        },
 
        clone: function( events ) {
@@ -294,33 +333,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;
@@ -338,6 +381,23 @@ jQuery.fn = jQuery.prototype = {
                        }) ), "filter", selector );
        },
 
+       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 ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
+                                       jQuery.data(cur, "closest", closer);
+                                       return cur;
+                               }
+                               cur = cur.parentNode;
+                               closer++;
+                       }
+               });
+       },
+
        not: function( selector ) {
                if ( typeof selector === "string" )
                        // test special case where just one selector is passed in
@@ -446,7 +506,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 );
        },
@@ -474,42 +534,17 @@ jQuery.fn = jQuery.prototype = {
                return this.add( this.prevObject );
        },
 
-       data: function( key, value ){
-               var parts = key.split(".");
-               parts[1] = parts[1] ? "." + parts[1] : "";
-
-               if ( value === undefined ) {
-                       var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
-
-                       if ( data === undefined && this.length )
-                               data = jQuery.data( this[0], key );
-
-                       return data == null && parts[1] ?
-                               this.data( parts[0] ) :
-                               data;
-               } else
-                       return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
-                               jQuery.data( this, key, value );
-                       });
-       },
-
-       removeData: function( key ){
-               return this.each(function(){
-                       jQuery.removeData( this, key );
-               });
-       },
-
        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 );
                }
@@ -597,9 +632,8 @@ jQuery.extend = jQuery.fn.extend = function() {
        return target;
 };
 
-var expando = "jQuery" + now(), uuid = 0, windowData = {},
-       // exclude the following css properties to add px
-       exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
+// exclude the following css properties to add px
+var    exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
        // cache defaultView
        defaultView = document.defaultView || {},
        toString = Object.prototype.toString;
@@ -627,15 +661,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 && elem.ownerDocument.documentElement.nodeName !== "HTML";
        },
 
        // 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,
@@ -658,74 +690,6 @@ jQuery.extend({
                return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
        },
 
-       cache: {},
-
-       data: function( elem, name, data ) {
-               elem = elem == window ?
-                       windowData :
-                       elem;
-
-               var id = elem[ expando ];
-
-               // Compute a unique ID for the element
-               if ( !id )
-                       id = elem[ expando ] = ++uuid;
-
-               // Only generate the data cache if we're
-               // trying to access or manipulate it
-               if ( name && !jQuery.cache[ id ] )
-                       jQuery.cache[ id ] = {};
-
-               // Prevent overriding the named cache with undefined values
-               if ( data !== undefined )
-                       jQuery.cache[ id ][ name ] = data;
-
-               // Return the named cache data, or the ID for the element
-               return name ?
-                       jQuery.cache[ id ][ name ] || null :
-                       id;
-       },
-
-       removeData: function( elem, name ) {
-               elem = elem == window ?
-                       windowData :
-                       elem;
-
-               var id = elem[ expando ];
-
-               // If we want to remove a specific section of the element's data
-               if ( name ) {
-                       if ( jQuery.cache[ id ] ) {
-                               // Remove the section of cache data
-                               delete jQuery.cache[ id ][ name ];
-
-                               // If we've removed all the data, remove the element's cache
-                               name = "";
-
-                               for ( name in jQuery.cache[ id ] )
-                                       break;
-
-                               if ( !name )
-                                       jQuery.removeData( elem );
-                       }
-
-               // Otherwise, we want to remove all of the element's data
-               } else {
-                       // Clean up the element expando
-                       try {
-                               delete elem[ expando ];
-                       } catch(e){
-                               // IE has trouble directly removing the expando
-                               // but it's ok with using removeAttribute
-                               if ( elem.removeAttribute )
-                                       elem.removeAttribute( expando );
-                       }
-
-                       // Completely remove the data cache
-                       delete jQuery.cache[ id ];
-               }
-       },
-
        // args is for internal usage only
        each: function( object, callback, args ) {
                var name, i = 0, length = object.length;
@@ -754,17 +718,6 @@ jQuery.extend({
                return object;
        },
 
-       prop: function( elem, value, type, i, name ) {
-               // Handle executable functions
-               if ( jQuery.isFunction( value ) )
-                       value = value.call( elem, i );
-
-               // Handle passing in a number to a CSS property
-               return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
-                       value + "px" :
-                       value;
-       },
-
        className: {
                // internal only, use addClass("class")
                add: function( elem, classNames ) {
@@ -786,7 +739,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;
                }
        },
 
@@ -806,26 +759,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 );
@@ -898,13 +857,22 @@ jQuery.extend({
        },
 
        clean: function( elems, context, fragment ) {
-               var ret = [], scripts = [];
                context = context || document;
 
                // !context.createElement fails in IE with an error but returns typeof 'object'
                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){
                        if ( typeof elem === "number" )
                                elem += '';
@@ -922,7 +890,7 @@ jQuery.extend({
                                });
 
                                // Trim whitespace, otherwise indexOf won't work as expected
-                               var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div");
+                               var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
 
                                var wrap =
                                        // option or optgroup
@@ -962,11 +930,12 @@ jQuery.extend({
                                if ( !jQuery.support.tbody ) {
 
                                        // String was a <table>, *may* have spurious <tbody>
-                                       var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
-                                               div.firstChild && div.firstChild.childNodes :
+                                       var hasBody = /<tbody/i.test(elem),
+                                               tbody = !tags.indexOf("<table") && !hasBody ?
+                                                       div.firstChild && div.firstChild.childNodes :
 
                                                // String was a bare <thead> or <tfoot>
-                                               wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
+                                               wrap[1] == "<table>" && !hasBody ?
                                                        div.childNodes :
                                                        [];
 
@@ -980,15 +949,6 @@ jQuery.extend({
                                if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
                                        div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
                                
-                               if ( fragment ) {
-                                       var found = div.getElementsByTagName("script");
-                       
-                                       while ( found.length ) {
-                                               scripts.push( found[0] );
-                                               found[0].parentNode.removeChild( found[0] );
-                                       }
-                               }
-
                                elem = jQuery.makeArray( div.childNodes );
                        }
 
@@ -998,14 +958,14 @@ jQuery.extend({
                                ret = jQuery.merge( ret, elem );
 
                });
-               
+
                if ( fragment ) {
                        for ( var i = 0; ret[i]; i++ ) {
-                               if ( jQuery.nodeName( ret[i], "script" ) ) {
-                                       ret[i].parentNode.removeChild( ret[i] );
+                               if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
+                                       scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
                                } else {
                                        if ( ret[i].nodeType === 1 )
-                                               ret = jQuery.merge( ret, ret[i].getElementsByTagName("script"));
+                                               ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
                                        fragment.appendChild( ret[i] );
                                }
                        }
@@ -1021,7 +981,7 @@ jQuery.extend({
                if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
                        return undefined;
 
-               var notxml = !jQuery.isXMLDoc( elem ),
+               var notxml = !elem.tagName || !jQuery.isXMLDoc( elem ),
                        // Whether we are setting (or getting)
                        set = value !== undefined;
 
@@ -1037,14 +997,14 @@ jQuery.extend({
 
                        // Safari mis-reports the default selected property of a hidden option
                        // Accessing the parent's selectedIndex property fixes it
-                       if ( name == "selected" )
+                       if ( name == "selected" && elem.parentNode )
                                elem.parentNode.selectedIndex;
 
                        // If applicable, access the attribute via the DOM 0 way
                        if ( name in elem && notxml && !special ) {
                                if ( set ){
                                        // We can't allow the type property to be changed (since it causes problems in IE)
-                                       if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
+                                       if ( name == "type" && elem.nodeName.match(/(button|input)/i) && elem.parentNode )
                                                throw "type property can't be changed";
 
                                        elem[ name ] = value;
@@ -1054,6 +1014,19 @@ jQuery.extend({
                                if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
                                        return elem.getAttributeNode( name ).nodeValue;
 
+                               // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+                               // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+                               if ( name == "tabIndex" ) {
+                                       var attributeNode = elem.getAttributeNode( "tabIndex" );
+                                       return attributeNode && attributeNode.specified
+                                               ? attributeNode.value
+                                               : elem.nodeName.match(/(button|input|object|select|textarea)/i)
+                                                       ? 0
+                                                       : elem.nodeName.match(/^(a|area)$/i) && elem.href
+                                                               ? 0
+                                                               : undefined;
+                               }
+
                                return elem[ name ];
                        }
 
@@ -1138,12 +1111,12 @@ jQuery.extend({
                // Also, we need to make sure that the correct elements are being returned
                // (IE returns comment nodes in a '*' query)
                if ( !jQuery.support.getAll ) {
-                       while ( (elem = second[ i++ ]) )
+                       while ( (elem = second[ i++ ]) != null )
                                if ( elem.nodeType != 8 )
                                        first[ pos++ ] = elem;
 
                } else
-                       while ( (elem = second[ i++ ]) )
+                       while ( (elem = second[ i++ ]) != null )
                                first[ pos++ ] = elem;
 
                return first;
@@ -1198,6 +1171,9 @@ jQuery.extend({
        }
 });
 
+// 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.
@@ -1213,9 +1189,6 @@ jQuery.browser = {
        mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
 };
 
-// Check to see if the W3C box model is being used
-jQuery.boxModel = !jQuery.browser.msie || document.compatMode == "CSS1Compat";
-
 jQuery.each({
        parent: function(elem){return elem.parentNode;},
        parents: function(elem){return jQuery.dir(elem,"parentNode");},
@@ -1244,13 +1217,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 );
        };
 });
 
@@ -1269,29 +1245,35 @@ jQuery.each({
                jQuery.className.remove( this, classNames );
        },
 
-       toggleClass: function( classNames ) {
-               jQuery.className[ jQuery.className.has( this, classNames ) ? "remove" : "add" ]( this, classNames );
+       toggleClass: function( classNames, state ) {
+               if( typeof state !== "boolean" )
+                       state = !jQuery.className.has( this, classNames );
+               jQuery.className[ state ? "add" : "remove" ]( this, classNames );
        },
 
        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(){
@@ -1299,7 +1281,11 @@ jQuery.each({
        };
 });
 
-// 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;
+function cleanData( elems ) {
+       for ( var i = 0, l = elems.length; i < l; i++ ) {
+               var id = elems[i][expando];
+               if ( id ) {
+                       delete jQuery.cache[ id ];
+               }
+       }
 }