Landing pull request 332. Appending disconnected radio or checkbox inputs and keeping checked setting Fixes #8060, #8500.

More Details:
 - https://github.com/jquery/jquery/pull/332
 - http://bugs.jquery.com/ticket/8060
 - http://bugs.jquery.com/ticket/8500
This commit is contained in:
timmywil 2011-04-21 21:51:23 -04:00 committed by jeresig
parent 3ac9eb7ce3
commit d274b7b9f7
4 changed files with 95 additions and 44 deletions

View file

@ -731,7 +731,7 @@ jQuery.extend({
} }
} }
// Go thorugh every key on the object, // Go through every key on the object,
} else { } else {
for ( key in elems ) { for ( key in elems ) {
value = callback( elems[ key ], key, arg ); value = callback( elems[ key ], key, arg );

View file

@ -379,13 +379,13 @@ function cloneCopyEvent( src, dest ) {
} }
function cloneFixAttributes( src, dest ) { function cloneFixAttributes( src, dest ) {
var nodeName;
// We do not need to do anything for non-Elements // We do not need to do anything for non-Elements
if ( dest.nodeType !== 1 ) { if ( dest.nodeType !== 1 ) {
return; return;
} }
var nodeName = dest.nodeName.toLowerCase();
// clearAttributes removes the attributes, which we don't want, // clearAttributes removes the attributes, which we don't want,
// but also removes the attachEvent events, which we *do* want // but also removes the attachEvent events, which we *do* want
if ( dest.clearAttributes ) { if ( dest.clearAttributes ) {
@ -398,6 +398,8 @@ function cloneFixAttributes( src, dest ) {
dest.mergeAttributes( src ); dest.mergeAttributes( src );
} }
nodeName = dest.nodeName.toLowerCase();
// IE6-8 fail to clone children inside object elements that use // IE6-8 fail to clone children inside object elements that use
// the proprietary classid attribute value (rather than the type // the proprietary classid attribute value (rather than the type
// attribute) to identify the type of content to display // attribute) to identify the type of content to display
@ -446,13 +448,12 @@ jQuery.buildFragment = function( args, nodes, scripts ) {
args[0].charAt(0) === "<" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) { args[0].charAt(0) === "<" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
cacheable = true; cacheable = true;
cacheresults = jQuery.fragments[ args[0] ]; cacheresults = jQuery.fragments[ args[0] ];
if ( cacheresults ) { if ( cacheresults && cacheresults !== 1 ) {
if ( cacheresults !== 1 ) {
fragment = cacheresults; fragment = cacheresults;
} }
} }
}
if ( !fragment ) { if ( !fragment ) {
fragment = doc.createDocumentFragment(); fragment = doc.createDocumentFragment();
@ -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({ jQuery.extend({
clone: function( elem, dataAndEvents, deepDataAndEvents ) { clone: function( elem, dataAndEvents, deepDataAndEvents ) {
var clone = elem.cloneNode(true), var clone = elem.cloneNode(true),
@ -578,10 +594,10 @@ jQuery.extend({
} }
// Convert html string into DOM nodes // Convert html string into DOM nodes
if ( typeof elem === "string" && !rhtml.test( elem ) ) { if ( typeof elem === "string" ) {
if ( !rhtml.test( elem ) ) {
elem = context.createTextNode( elem ); elem = context.createTextNode( elem );
} else {
} else if ( typeof elem === "string" ) {
// Fix "XHTML"-style tags in all browsers // Fix "XHTML"-style tags in all browsers
elem = elem.replace(rxhtmlTag, "<$1></$2>"); elem = elem.replace(rxhtmlTag, "<$1></$2>");
@ -617,7 +633,6 @@ jQuery.extend({
tbody[ j ].parentNode.removeChild( tbody[ j ] ); tbody[ j ].parentNode.removeChild( tbody[ j ] );
} }
} }
} }
// IE completely kills leading whitespace when innerHTML is used // IE completely kills leading whitespace when innerHTML is used
@ -627,6 +642,20 @@ jQuery.extend({
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 ) { if ( elem.nodeType ) {
ret.push( elem ); ret.push( elem );

View file

@ -186,6 +186,14 @@ jQuery.support = (function() {
support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
div.innerHTML = ""; 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 // Check if div with explicit width and no margin-right incorrectly
// gets computed margin-right based on width of container. For more // gets computed margin-right based on width of container. For more
// info see bug #3333 // info see bug #3333

View file

@ -227,7 +227,7 @@ test("unwrap()", function() {
}); });
var testAppend = function(valueObj) { var testAppend = function(valueObj) {
expect(37); expect(40);
var defaultText = "Try them out:" var defaultText = "Try them out:"
var result = jQuery("#first").append(valueObj("<b>buga</b>")); var result = jQuery("#first").append(valueObj("<b>buga</b>"));
equals( result.text(), defaultText + "buga", "Check if text appending works" ); equals( result.text(), defaultText + "buga", "Check if text appending works" );
@ -330,6 +330,20 @@ var testAppend = function(valueObj) {
d.contents().appendTo("#nonnodes"); d.contents().appendTo("#nonnodes");
d.remove(); d.remove();
ok( jQuery("#nonnodes").contents().length >= 2, "Check node,textnode,comment append cleanup worked" ); 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() { test("append(String|Element|Array&lt;Element&gt;|jQuery)", function() {