diff options
author | Michael Monteleone <michael@michaelmonteleone.net> | 2010-01-25 18:43:33 -0500 |
---|---|---|
committer | jeresig <jeresig@gmail.com> | 2010-01-25 18:43:33 -0500 |
commit | bed759c95ca6d796125653b540e8611dc63b38bb (patch) | |
tree | bc8fcc3811466fd18913fd2604586b8c6a96bb04 | |
parent | 390186b902c4c1ac13e23754d33ed4d8b3d5fa38 (diff) | |
download | jquery-bed759c95ca6d796125653b540e8611dc63b38bb.tar.gz jquery-bed759c95ca6d796125653b540e8611dc63b38bb.zip |
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.
-rw-r--r-- | src/manipulation.js | 15 | ||||
-rw-r--r-- | src/support.js | 11 | ||||
-rw-r--r-- | test/unit/manipulation.js | 20 |
3 files changed, 41 insertions, 5 deletions
diff --git a/src/manipulation.js b/src/manipulation.js index 23463d16e..4d0ffd057 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 3e9977278..befc53272 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 031bf5b72..b0a1c71af 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') )); |