Greatly reduced the complexity of the width/height methods. This also fixes #2009...
[jquery.git] / src / core.js
index 0bf3530..660f7ee 100644 (file)
@@ -14,10 +14,8 @@ if ( window.jQuery )
        var _jQuery = window.jQuery;
 
 var jQuery = window.jQuery = function( selector, context ) {
-       // If the context is a namespace object, return a new object
-       return this instanceof jQuery ?
-               this.init( selector, context ) :
-               new jQuery( selector, context );
+       // The jQuery object is actually just the init constructor 'enhanced'
+       return new jQuery.prototype.init( selector, context );
 };
 
 // Map over the $ in case of overwrite
@@ -202,7 +200,7 @@ jQuery.fn = jQuery.prototype = {
 
        text: function( text ) {
                if ( typeof text != "object" && text != null )
-                       return this.empty().append( document.createTextNode( text ) );
+                       return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
 
                var ret = "";
 
@@ -251,13 +249,15 @@ jQuery.fn = jQuery.prototype = {
 
        append: function() {
                return this.domManip(arguments, true, false, function(elem){
-                       this.appendChild( elem );
+                       if (this.nodeType == 1)
+                               this.appendChild( elem );
                });
        },
 
        prepend: function() {
                return this.domManip(arguments, true, true, function(elem){
-                       this.insertBefore( elem, this.firstChild );
+                       if (this.nodeType == 1)
+                               this.insertBefore( elem, this.firstChild );
                });
        },
        
@@ -290,9 +290,23 @@ jQuery.fn = jQuery.prototype = {
        clone: function( events ) {
                // Do the clone
                var ret = this.map(function(){
-                       return this.outerHTML ?
-                               jQuery( this.outerHTML )[0] :
-                               this.cloneNode( true );
+                       if ( jQuery.browser.msie ) {
+                               // IE copies events bound via attachEvent when
+                               // using cloneNode. Calling detachEvent on the
+                               // clone will also remove the events from the orignal
+                               // In order to get around this, we use innerHTML.
+                               // Unfortunately, this means some modifications to 
+                               // 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"),
+                                       container2 = document.createElement("div");
+                               container.appendChild(clone);
+                               container2.innerHTML = container.innerHTML;
+                               return container2.firstChild;
+                       } else
+                               return this.cloneNode(true);
                });
 
                // Need to set the expando to null on the cloned set if it exists
@@ -340,7 +354,7 @@ jQuery.fn = jQuery.prototype = {
        },
 
        add: function( selector ) {
-               return this.pushStack( jQuery.merge( 
+               return !selector ? this : this.pushStack( jQuery.merge( 
                        this.get(),
                        selector.constructor == String ? 
                                jQuery( selector ).get() :
@@ -402,6 +416,9 @@ jQuery.fn = jQuery.prototype = {
 
                } else
                        return this.each(function(){
+                               if ( this.nodeType != 1 )
+                                       return;
+
                                if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
                                        this.checked = (jQuery.inArray(this.value, value) >= 0 ||
                                                jQuery.inArray(this.name, value) >= 0);
@@ -468,7 +485,7 @@ jQuery.fn = jQuery.prototype = {
                        var obj = this;
 
                        if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
-                               obj = this.getElementsByTagName("tbody")[0] || this.appendChild( document.createElement("tbody") );
+                               obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );
 
                        var scripts = jQuery( [] );
 
@@ -477,16 +494,9 @@ jQuery.fn = jQuery.prototype = {
                                        this.cloneNode( true ) :
                                        this;
 
+                               // execute all scripts after the elements have been injected
                                if ( jQuery.nodeName( elem, "script" ) ) {
-
-                                       // If scripts are waiting to be executed, wait on this script as well
-                                       if ( scripts.length )
-                                               scripts = scripts.add( elem );
-
-                                       // If nothing is waiting to be executed, run immediately
-                                       else
-                                               evalScript( 0, elem );
-
+                                       scripts = scripts.add( elem );
                                } else {
                                        // Remove any inner scripts for later evaluation
                                        if ( elem.nodeType == 1 )
@@ -502,6 +512,9 @@ jQuery.fn = jQuery.prototype = {
        }
 };
 
+// Give the init function the jQuery prototype for later instantiation
+jQuery.prototype.init.prototype = jQuery.prototype;
+
 function evalScript( i, elem ) {
        if ( elem.src )
                jQuery.ajax({
@@ -530,7 +543,7 @@ jQuery.extend = jQuery.fn.extend = function() {
        }
 
        // Handle case when target is a string or something (possible in deep copy)
-       if ( typeof target != "object" )
+       if ( typeof target != "object" && typeof target != "function" )
                target = {};
 
        // extend jQuery itself if only one argument is passed
@@ -722,18 +735,19 @@ jQuery.extend({
                // internal only, use addClass("class")
                add: function( elem, classNames ) {
                        jQuery.each((classNames || "").split(/\s+/), function(i, className){
-                               if ( !jQuery.className.has( elem.className, className ) )
+                               if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
                                        elem.className += (elem.className ? " " : "") + className;
                        });
                },
 
                // internal only, use removeClass("class")
                remove: function( elem, classNames ) {
-                       elem.className = classNames != undefined ?
-                               jQuery.grep(elem.className.split(/\s+/), function(className){
-                                       return !jQuery.className.has( classNames, className );  
-                               }).join(" ") :
-                               "";
+                       if (elem.nodeType == 1)
+                               elem.className = classNames != undefined ?
+                                       jQuery.grep(elem.className.split(/\s+/), function(className){
+                                               return !jQuery.className.has( classNames, className );  
+                                       }).join(" ") :
+                                       "";
                },
 
                // internal only, use is(".class")
@@ -758,55 +772,22 @@ jQuery.extend({
        },
 
        css: function( elem, name, force ) {
-               if ( name == "height" || name == "width" ) {
-                       var old = {}, height, width;
-
-                       // Revert the padding and border widths to get the
-                       // correct height/width values
-                       jQuery.each([ "Top", "Bottom", "Right", "Left" ], function(){
-                               old[ "padding" + this ] = 0;
-                               old[ "border" + this + "Width" ] = 0;
-                       });
-
-                       // Swap out the padding/border values temporarily
-                       jQuery.swap( elem, old, function() {
-
-                               // If the element is visible, then the calculation is easy
-                               if ( jQuery( elem ).is(":visible") ) {
-                                       height = elem.offsetHeight;
-                                       width = elem.offsetWidth;
-
-                               // Otherwise, we need to flip out more values
-                               } else {
-                                       elem = jQuery( elem.cloneNode(true) )
-                                               .find(":radio").removeAttr("checked").removeAttr("defaultChecked").end()
-                                               .css({
-                                                       visibility: "hidden",
-                                                       position: "absolute",
-                                                       display: "block",
-                                                       right: "0",
-                                                       left: "0"
-                                               }).appendTo( elem.parentNode )[0];
-
-                                       var position = jQuery.css( elem.parentNode, "position" ) || "static";
-                                       if ( position == "static" )
-                                               elem.parentNode.style.position = "relative";
-
-                                       height = elem.clientHeight;
-                                       width = elem.clientWidth;
-
-                                       if ( position == "static" )
-                                               elem.parentNode.style.position = "static";
-
-                                       elem.parentNode.removeChild( elem );
-                               }
-                       });
+               if ( name == "width" || name == "height" ) {
+                       var width, height, props = { position: "absolute", visibility: "hidden", display:"block" };
+               
+                       function getWH() {
+                               width = elem.clientWidth;
+                               height = elem.clientHeight;
+                       }
+               
+                       if ( jQuery(elem).is(":visible") )
+                               getWH();
+                       else
+                               jQuery.swap( elem, props, getWH );
 
-                       return name == "height" ?
-                               height :
-                               width;
+                       return name == "width" ? width : height;
                }
-
+               
                return jQuery.curCSS( elem, name, force );
        },
 
@@ -917,6 +898,9 @@ jQuery.extend({
        clean: function( elems, context ) {
                var ret = [];
                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;
 
                jQuery.each(elems, function(i, elem){
                        if ( !elem )
@@ -1011,6 +995,10 @@ jQuery.extend({
        },
        
        attr: function( elem, name, value ) {
+               // don't set attributes on text and comment nodes
+               if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
+                       return undefined;
+
                var fix = jQuery.isXMLDoc( elem ) ?
                        {} :
                        jQuery.props;
@@ -1064,7 +1052,7 @@ jQuery.extend({
                                                (parseFloat( value ).toString() == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
                                }
        
-                               return elem.filter ? 
+                               return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
                                        (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100).toString() :
                                        "";
                        }
@@ -1264,7 +1252,8 @@ jQuery.each({
 jQuery.each({
        removeAttr: function( name ) {
                jQuery.attr( this, name, "" );
-               this.removeAttribute( name );
+               if (this.nodeType == 1) 
+                       this.removeAttribute( name );
        },
 
        addClass: function( classNames ) {