Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Landing pull request 332. Appending disconnected radio or checkbox in…

…puts and keeping checked setting Fixes #8060, #8500.

More Details:
 - #332
 - http://bugs.jquery.com/ticket/8060
 - http://bugs.jquery.com/ticket/8500
  • Loading branch information...
commit d274b7b9f7727e8bccd6906d954e4dc790404d23 1 parent 3ac9eb7
timmywil authored jeresig committed
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
113 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;
}
}
@@ -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 ) {
View
8 src/support.js
@@ -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
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() {
Please sign in to comment.
Something went wrong with that request. Please try again.