Ensure that buildFragment clones elements properly in all browsers. Fixes #3879,...
authorColin Snover <github.com@zetafleet.com>
Mon, 10 Jan 2011 00:38:44 +0000 (18:38 -0600)
committerColin Snover <github.com@zetafleet.com>
Mon, 10 Jan 2011 00:38:44 +0000 (18:38 -0600)
src/core.js
src/manipulation.js
test/unit/core.js
test/unit/manipulation.js

index b9e6d81..4361577 100644 (file)
@@ -129,7 +129,7 @@ jQuery.fn = jQuery.prototype = {
 
                                        } else {
                                                ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
 
                                        } else {
                                                ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
-                                               selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
+                                               selector = (ret.cacheable ? jQuery(ret.fragment).clone()[0] : ret.fragment).childNodes;
                                        }
 
                                        return jQuery.merge( this, selector );
                                        }
 
                                        return jQuery.merge( this, selector );
index 4930822..cf533c8 100644 (file)
@@ -420,15 +420,29 @@ function cloneFixAttributes(src, dest) {
        if ( nodeName === "object" ) {
                dest.outerHTML = src.outerHTML;
 
        if ( nodeName === "object" ) {
                dest.outerHTML = src.outerHTML;
 
-       // IE6-8 fails to persist the checked state of a cloned checkbox
-       // or radio button
-       } else if ( nodeName === "input" && src.checked ) {
-               dest.defaultChecked = dest.checked = src.checked;
+       } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
+               // IE6-8 fails to persist the checked state of a cloned checkbox
+               // or radio button. Worse, IE6-7 fail to give the cloned element
+               // a checked appearance if the defaultChecked value isn't also set
+               if ( src.checked ) {
+                       dest.defaultChecked = dest.checked = src.checked;
+               }
+
+               // IE6-7 get confused and end up setting the value of a cloned
+               // checkbox/radio button to an empty string instead of "on"
+               if ( dest.value !== src.value ) {
+                       dest.value = src.value;
+               }
 
        // IE6-8 fails to return the selected option to the default selected
        // state when cloning options
        } else if ( nodeName === "option" ) {
                dest.selected = src.defaultSelected;
 
        // IE6-8 fails to return the selected option to the default selected
        // state when cloning options
        } else if ( nodeName === "option" ) {
                dest.selected = src.defaultSelected;
+
+       // IE6-8 fails to set the defaultValue to the correct value when
+       // cloning other types of input fields
+       } else if ( nodeName === "input" || nodeName === "textarea" ) {
+               dest.defaultValue = src.defaultValue;
        }
 
        // Event data gets referenced instead of copied if the expando
        }
 
        // Event data gets referenced instead of copied if the expando
index 8fd0605..bfb2f1c 100644 (file)
@@ -12,7 +12,7 @@ test("Basic requirements", function() {
 });
 
 test("jQuery()", function() {
 });
 
 test("jQuery()", function() {
-       expect(23);
+       expect(24);
 
        // Basic constructor's behavior
 
 
        // Basic constructor's behavior
 
@@ -84,6 +84,11 @@ test("jQuery()", function() {
 
        exec = true;
        elem.click();
 
        exec = true;
        elem.click();
+
+       for ( var i = 0; i < 3; ++i ) {
+               elem = jQuery("<input type='text' value='TEST' />");
+       }
+       equals( elem[0].defaultValue, "TEST", "Ensure cached nodes are cloned properly (Bug #6655)" );
 });
 
 test("selector state", function() {
 });
 
 test("selector state", function() {
index e273cf0..559a076 100644 (file)
@@ -395,7 +395,7 @@ test("append(Function) with incoming value", function() {
 });
 
 test("append the same fragment with events (Bug #6997, 5566)", function () {
 });
 
 test("append the same fragment with events (Bug #6997, 5566)", function () {
-       expect(4 + (document.fireEvent ? 1 : 0));
+       expect(2 + (document.fireEvent ? 1 : 0));
        stop(1000);
 
        var element;
        stop(1000);
 
        var element;
@@ -426,14 +426,6 @@ test("append the same fragment with events (Bug #6997, 5566)", function () {
 
        jQuery("#listWithTabIndex li").before(element);
        jQuery("#listWithTabIndex li.test6997").eq(1).click();
 
        jQuery("#listWithTabIndex li").before(element);
        jQuery("#listWithTabIndex li.test6997").eq(1).click();
-
-       element = jQuery("<select><option>Foo</option><option selected>Bar</option></select>");
-
-       equals( element.clone().find("option:selected").val(), element.find("option:selected").val(), "Selected option cloned correctly" );
-
-       element = jQuery("<input type='checkbox'>").attr('checked', 'checked');
-
-       equals( element.clone().is(":checked"), element.is(":checked"), "Checked input cloned correctly" );
 });
 
 test("appendTo(String|Element|Array&lt;Element&gt;|jQuery)", function() {
 });
 
 test("appendTo(String|Element|Array&lt;Element&gt;|jQuery)", function() {
@@ -945,6 +937,28 @@ test("clone()", function() {
        equal( jQuery("body").clone().children()[0].id, "qunit-header", "Make sure cloning body works" );
 });
 
        equal( jQuery("body").clone().children()[0].id, "qunit-header", "Make sure cloning body works" );
 });
 
+test("clone(form element) (Bug #3879, #6655)", function() {
+       expect(6);
+       element = jQuery("<select><option>Foo</option><option selected>Bar</option></select>");
+
+       equals( element.clone().find("option:selected").val(), element.find("option:selected").val(), "Selected option cloned correctly" );
+
+       element = jQuery("<input type='checkbox' value='foo'>").attr('checked', 'checked');
+       clone = element.clone();
+
+       equals( clone.is(":checked"), element.is(":checked"), "Checked input cloned correctly" );
+       equals( clone[0].defaultValue, "foo", "Checked input defaultValue cloned correctly" );
+       equals( clone[0].defaultChecked, !jQuery.support.noCloneEvent, "Checked input defaultChecked cloned correctly" );
+
+       element = jQuery("<input type='text' value='foo'>");
+       clone = element.clone();
+       equals( clone[0].defaultValue, "foo", "Text input defaultValue cloned correctly" );
+
+       element = jQuery("<textarea>foo</textarea>");
+       clone = element.clone();
+       equals( clone[0].defaultValue, "foo", "Textarea defaultValue cloned correctly" );
+});
+
 if (!isLocal) {
 test("clone() on XML nodes", function() {
        expect(2);
 if (!isLocal) {
 test("clone() on XML nodes", function() {
        expect(2);