Skip to content
Browse files

#8500 and #8060 - Checked attribute did not carry over once a discon…

…nected radio or checkbox is appended to the DOM

- Cleaned up some code in $.fn.clean (badum-psh)
  • Loading branch information...
1 parent 230a50f commit 0bcbbde7856b88e279f7be6bb767f48bdab51e9e timmywil committed Apr 17, 2011
Showing with 89 additions and 45 deletions.
  1. +1 −1 src/core.js
  2. +67 −43 src/manipulation.js
  3. +6 −0 src/support.js
  4. +15 −1 test/unit/manipulation.js
View
2 src/core.js
@@ -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 );
View
110 src/manipulation.js
@@ -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;
}
}
@@ -557,7 +558,7 @@ jQuery.extend({
},
clean: function( elems, context, fragment, scripts ) {
- var checkScriptType;
+ var checkScriptType, fixChecked, len;
context = context || document;
@@ -578,54 +579,77 @@ 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)
+ if ( !jQuery.support.appendChecked ) {
+ fixChecked = function( elem ) {
+ if ( jQuery.nodeName( elem, "input" ) && (elem.type === "checkbox" || elem.type === "radio") ) {
+ elem.defaultChecked = elem.checked;
+ }
+ };
+
+ if ( elem[0] && typeof elem.length === "number" ) {
+ for ( i = 0, len = elem.length; i < len; i++ ) {
+ if ( elem[i].getElementsByTagName ) {
+ fixChecked( elem[i] );
+ jQuery.grep( elem[i].getElementsByTagName("input"), fixChecked );
+ }
+ }
+ } else {
+ if ( elem.getElementsByTagName ) {
+ fixChecked( elem );
+ jQuery.grep( elem.getElementsByTagName("input"), fixChecked );
+ }
+ }
}
if ( elem.nodeType ) {
View
6 src/support.js
@@ -185,6 +185,12 @@ jQuery.support = (function() {
support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
div.innerHTML = "";
+ 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
View
16 test/unit/manipulation.js
@@ -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() {

0 comments on commit 0bcbbde

Please sign in to comment.
Something went wrong with that request. Please try again.