From: Michael Monteleone <michael@michaelmonteleone.net>
Date: Mon, 25 Jan 2010 23:43:33 +0000 (-0500)
Subject: Make sure that checked state is cloned properly. Based upon the patch by Michael... 
X-Git-Url: http://git.asbjorn.biz/?a=commitdiff_plain;h=bed759c95ca6d796125653b540e8611dc63b38bb;p=jquery.git

Make sure that checked state is cloned properly. Based upon the patch by Michael, required better test cases and in doing so found more edge cases. Introduced a new check into jQuery.support as a result. Fixes #5929.
---

diff --git a/src/manipulation.js b/src/manipulation.js
index 23463d1..4d0ffd0 100644
--- a/src/manipulation.js
+++ b/src/manipulation.js
@@ -5,6 +5,7 @@ var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
 	rtagName = /<([\w:]+)/,
 	rtbody = /<tbody/i,
 	rhtml = /<|&\w+;/,
+	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,  // checked="checked" or checked (html5)
 	fcloseTag = function( all, front, tag ) {
 		return rselfClosing.test( tag ) ?
 			all :
@@ -35,7 +36,7 @@ jQuery.fn.extend({
 		if ( jQuery.isFunction(text) ) {
 			return this.each(function(i) {
 				var self = jQuery(this);
-				return self.text( text.call(this, i, self.text()) );
+				self.text( text.call(this, i, self.text()) );
 			});
 		}
 
@@ -251,11 +252,18 @@ jQuery.fn.extend({
 	domManip: function( args, table, callback ) {
 		var results, first, value = args[0], scripts = [];
 
+		// We can't cloneNode fragments that contain checked, in WebKit
+		if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
+			return this.each(function() {
+				jQuery(this).domManip( args, table, callback, true );
+			});
+		}
+
 		if ( jQuery.isFunction(value) ) {
 			return this.each(function(i) {
 				var self = jQuery(this);
 				args[0] = value.call(this, i, table ? self.html() : undefined);
-				return self.domManip( args, table, callback );
+				self.domManip( args, table, callback );
 			});
 		}
 
@@ -326,7 +334,8 @@ function cloneCopyEvent(orig, ret) {
 function buildFragment( args, nodes, scripts ) {
 	var fragment, cacheable, cacheresults, doc;
 
-	if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && args[0].indexOf("<option") < 0 ) {
+	// webkit does not clone 'checked' attribute of radio inputs on cloneNode, so don't cache if string has a checked
+	if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && args[0].indexOf("<option") < 0 && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
 		cacheable = true;
 		cacheresults = jQuery.fragments[ args[0] ];
 		if ( cacheresults ) {
diff --git a/src/support.js b/src/support.js
index 3e99772..befc532 100644
--- a/src/support.js
+++ b/src/support.js
@@ -57,6 +57,7 @@
 		optSelected: document.createElement("select").appendChild( document.createElement("option") ).selected,
 
 		// Will be defined later
+		checkClone: false,
 		scriptEval: false,
 		noCloneEvent: true,
 		boxModel: null
@@ -89,9 +90,17 @@
 		div.cloneNode(true).fireEvent("onclick");
 	}
 
+	div = document.createElement("div");
+	div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>";
+
+	var fragment = document.createDocumentFragment();
+	fragment.appendChild( div.firstChild );
+
+	// WebKit doesn't clone checked state correctly in fragments
+	jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;
+
 	// Figure out if the W3C box model works as expected
 	// document.body must exist before we can do this
-	// TODO: This timeout is temporary until I move ready into core.js.
 	jQuery(function() {
 		var div = document.createElement("div");
 		div.style.width = div.style.paddingLeft = "1px";
diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js
index 031bf5b..b0a1c71 100644
--- a/test/unit/manipulation.js
+++ b/test/unit/manipulation.js
@@ -197,7 +197,7 @@ test("unwrap()", function() {
 });
 
 var testAppend = function(valueObj) {
-	expect(22);
+	expect(37);
 	var defaultText = 'Try them out:'
 	var result = jQuery('#first').append(valueObj('<b>buga</b>'));
 	equals( result.text(), defaultText + 'buga', 'Check if text appending works' );
@@ -230,6 +230,24 @@ var testAppend = function(valueObj) {
 	ok( jQuery("#sap").append(valueObj( [] )), "Check for appending an empty array." );
 	ok( jQuery("#sap").append(valueObj( "" )), "Check for appending an empty string." );
 	ok( jQuery("#sap").append(valueObj( document.getElementsByTagName("foo") )), "Check for appending an empty nodelist." );
+	
+	reset();
+	jQuery("form").append(valueObj('<input name="radiotest" type="radio" checked="checked" />'));
+	jQuery("form input[name=radiotest]").each(function(){
+		ok( jQuery(this).is(':checked'), "Append checked radio");
+	}).remove();
+
+	reset();
+	jQuery("form").append(valueObj('<input name="radiotest" type="radio" checked    =   \'checked\' />'));
+	jQuery("form input[name=radiotest]").each(function(){
+		ok( jQuery(this).is(':checked'), "Append alternately formated checked radio");
+	}).remove();
+
+	reset();
+	jQuery("form").append(valueObj('<input name="radiotest" type="radio" checked />'));
+	jQuery("form input[name=radiotest]").each(function(){
+		ok( jQuery(this).is(':checked'), "Append HTML5-formated checked radio");
+	}).remove();
 
 	reset();
 	jQuery("#sap").append(valueObj( document.getElementById('form') ));