]> source.dussan.org Git - jquery.git/commitdiff
Landing pull request 332. Appending disconnected radio or checkbox inputs and keeping...
authortimmywil <tim.willison@thisismedium.com>
Fri, 22 Apr 2011 01:51:23 +0000 (21:51 -0400)
committerjeresig <jeresig@gmail.com>
Fri, 22 Apr 2011 01:51:23 +0000 (21:51 -0400)
More Details:
 - https://github.com/jquery/jquery/pull/332
 - http://bugs.jquery.com/ticket/8060
 - http://bugs.jquery.com/ticket/8500

src/core.js
src/manipulation.js
src/support.js
test/unit/manipulation.js

index a82a2fdced2018b9d0923f4c91854e1bcfd46dbd..8d812e3842878a1a97776a4bdef6b261b693c1b0 100644 (file)
@@ -731,7 +731,7 @@ jQuery.extend({
                                }
                        }
 
-               // Go thorugh every key on the object,
+               // Go through every key on the object,
                } else {
                        for ( key in elems ) {
                                value = callback( elems[ key ], key, arg );
index f519b4d35a4984ddac9642d132e7ff78d73dae98..610d19b7ad0db25130fa3b896ac19bfe5eb8dba7 100644 (file)
@@ -70,7 +70,7 @@ jQuery.fn.extend({
                                }
 
                                return elem;
-                       }).append(this);
+                       }).append( this );
                }
 
                return this;
@@ -379,13 +379,13 @@ function cloneCopyEvent( src, dest ) {
 }
 
 function cloneFixAttributes( src, dest ) {
+       var nodeName;
+
        // We do not need to do anything for non-Elements
        if ( dest.nodeType !== 1 ) {
                return;
        }
 
-       var nodeName = dest.nodeName.toLowerCase();
-
        // clearAttributes removes the attributes, which we don't want,
        // but also removes the attachEvent events, which we *do* want
        if ( dest.clearAttributes ) {
@@ -398,6 +398,8 @@ function cloneFixAttributes( src, dest ) {
                dest.mergeAttributes( src );
        }
 
+       nodeName = dest.nodeName.toLowerCase();
+
        // IE6-8 fail to clone children inside object elements that use
        // the proprietary classid attribute value (rather than the type
        // attribute) to identify the type of content to display
@@ -446,11 +448,10 @@ jQuery.buildFragment = function( args, nodes, scripts ) {
                args[0].charAt(0) === "<" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
 
                cacheable = true;
+
                cacheresults = jQuery.fragments[ args[0] ];
-               if ( cacheresults ) {
-                       if ( cacheresults !== 1 ) {
-                               fragment = cacheresults;
-                       }
+               if ( cacheresults && cacheresults !== 1 ) {
+                       fragment = cacheresults;
                }
        }
 
@@ -508,6 +509,21 @@ function getAll( elem ) {
        }
 }
 
+// Used in clean, fixes the defaultChecked property
+function fixDefaultChecked( elem ) {
+       if ( elem.type === "checkbox" || elem.type === "radio" ) {
+               elem.defaultChecked = elem.checked;
+       }
+}
+// Finds all inputs and passes them to fixDefaultChecked
+function findInputs( elem ) {
+       if ( jQuery.nodeName( elem, "input" ) ) {
+               fixDefaultChecked( elem );
+       } else if ( elem.getElementsByTagName ) {
+               jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
+       }
+}
+
 jQuery.extend({
        clone: function( elem, dataAndEvents, deepDataAndEvents ) {
                var clone = elem.cloneNode(true),
@@ -578,54 +594,67 @@ jQuery.extend({
                        }
 
                        // Convert html string into DOM nodes
-                       if ( typeof elem === "string" && !rhtml.test( elem ) ) {
-                               elem = context.createTextNode( elem );
-
-                       } else if ( typeof elem === "string" ) {
-                               // Fix "XHTML"-style tags in all browsers
-                               elem = elem.replace(rxhtmlTag, "<$1></$2>");
+                       if ( typeof elem === "string" ) {
+                               if ( !rhtml.test( elem ) ) {
+                                       elem = context.createTextNode( elem );
+                               } else {
+                                       // Fix "XHTML"-style tags in all browsers
+                                       elem = elem.replace(rxhtmlTag, "<$1></$2>");
 
-                               // Trim whitespace, otherwise indexOf won't work as expected
-                               var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
-                                       wrap = wrapMap[ tag ] || wrapMap._default,
-                                       depth = wrap[0],
-                                       div = context.createElement("div");
+                                       // Trim whitespace, otherwise indexOf won't work as expected
+                                       var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
+                                               wrap = wrapMap[ tag ] || wrapMap._default,
+                                               depth = wrap[0],
+                                               div = context.createElement("div");
 
-                               // Go to html and back, then peel off extra wrappers
-                               div.innerHTML = wrap[1] + elem + wrap[2];
+                                       // Go to html and back, then peel off extra wrappers
+                                       div.innerHTML = wrap[1] + elem + wrap[2];
 
-                               // Move to the right depth
-                               while ( depth-- ) {
-                                       div = div.lastChild;
-                               }
+                                       // Move to the right depth
+                                       while ( depth-- ) {
+                                               div = div.lastChild;
+                                       }
 
-                               // Remove IE's autoinserted <tbody> from table fragments
-                               if ( !jQuery.support.tbody ) {
+                                       // Remove IE's autoinserted <tbody> from table fragments
+                                       if ( !jQuery.support.tbody ) {
 
-                                       // String was a <table>, *may* have spurious <tbody>
-                                       var hasBody = rtbody.test(elem),
-                                               tbody = tag === "table" && !hasBody ?
-                                                       div.firstChild && div.firstChild.childNodes :
+                                               // String was a <table>, *may* have spurious <tbody>
+                                               var hasBody = rtbody.test(elem),
+                                                       tbody = tag === "table" && !hasBody ?
+                                                               div.firstChild && div.firstChild.childNodes :
 
-                                                       // String was a bare <thead> or <tfoot>
-                                                       wrap[1] === "<table>" && !hasBody ?
-                                                               div.childNodes :
-                                                               [];
+                                                               // String was a bare <thead> or <tfoot>
+                                                               wrap[1] === "<table>" && !hasBody ?
+                                                                       div.childNodes :
+                                                                       [];
 
-                                       for ( var j = tbody.length - 1; j >= 0 ; --j ) {
-                                               if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
-                                                       tbody[ j ].parentNode.removeChild( tbody[ j ] );
+                                               for ( var j = tbody.length - 1; j >= 0 ; --j ) {
+                                                       if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
+                                                               tbody[ j ].parentNode.removeChild( tbody[ j ] );
+                                                       }
                                                }
                                        }
 
-                               }
+                                       // IE completely kills leading whitespace when innerHTML is used
+                                       if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+                                               div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
+                                       }
 
-                               // IE completely kills leading whitespace when innerHTML is used
-                               if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
-                                       div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
+                                       elem = div.childNodes;
                                }
+                       }
 
-                               elem = div.childNodes;
+                       // Resets defaultChecked for any radios and checkboxes
+                       // about to be appended to the DOM in IE 6/7 (#8060)
+                       var len;
+                       if ( !jQuery.support.appendChecked ) {
+                               if ( elem[0] && typeof (len = elem.length) === "number" ) {
+                                       for ( i = 0; i < len; i++ ) {
+                                               findInputs( elem[i] );
+                                       }
+                               } else {
+                                       findInputs( elem );
+                               }
                        }
 
                        if ( elem.nodeType ) {
index b286907ff80f3340c09c254dc28319d8209f4460..8f2beebbcd6de116fdbd98b8e3f1a9c31f8e8916 100644 (file)
@@ -186,6 +186,14 @@ jQuery.support = (function() {
        support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
        div.innerHTML = "";
 
+       // Check if a disconnected checkbox will retain its checked
+       // value of true after appended to the DOM
+       input = document.createElement("input");
+       input.setAttribute("type", "checkbox");
+       input.checked = true;
+       div.appendChild( input );
+       support.appendChecked = input.checked;
+
        // Check if div with explicit width and no margin-right incorrectly
        // gets computed margin-right based on width of container. For more
        // info see bug #3333
index e0fb369a61dc7734fcbc8f69c57f0c9c259023cf..b71b6962eac3ac8091df6469a6a900c48ce6ba94 100644 (file)
@@ -227,7 +227,7 @@ test("unwrap()", function() {
 });
 
 var testAppend = function(valueObj) {
-       expect(37);
+       expect(40);
        var defaultText = "Try them out:"
        var result = jQuery("#first").append(valueObj("<b>buga</b>"));
        equals( result.text(), defaultText + "buga", "Check if text appending works" );
@@ -330,6 +330,20 @@ var testAppend = function(valueObj) {
        d.contents().appendTo("#nonnodes");
        d.remove();
        ok( jQuery("#nonnodes").contents().length >= 2, "Check node,textnode,comment append cleanup worked" );
+
+       QUnit.reset();
+       var $input = jQuery("<input />").attr({ "type": "checkbox", "checked": true }).appendTo('#testForm');
+       equals( $input[0].checked, true, "A checked checkbox that is appended stays checked" );
+
+       QUnit.reset();
+       var $radios = jQuery("input:radio[name='R1']"),
+               $radioNot = jQuery("<input type='radio' name='R1' checked='checked'/>").insertAfter( $radios ),
+               $radio = $radios.eq(1).click();
+       $radioNot[0].checked = false;
+       $radios.parent().wrap("<div></div>");
+       equals( $radio[0].checked, true, "Reappending radios uphold which radio is checked" );
+       equals( $radioNot[0].checked, false, "Reappending radios uphold not being checked" );
+       QUnit.reset();
 }
 
 test("append(String|Element|Array&lt;Element&gt;|jQuery)", function() {