Skip to content

Commit

Permalink
Make a new jQuery.support.noCloneChecked - splitting apart the previo…
Browse files Browse the repository at this point in the history
…us feature detect relating to clone in IE, fixes the last remaining issue with IE 9 RC. Fixes #8365.
  • Loading branch information
jeresig committed Feb 23, 2011
1 parent 3663836 commit 292acd9
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 17 deletions.
34 changes: 22 additions & 12 deletions src/manipulation.js
Expand Up @@ -489,14 +489,27 @@ jQuery.each({
}; };
}); });


function getAll( elem ) {
if ( "getElementsByTagName" in elem ) {
return elem.getElementsByTagName( "*" );

} else if ( "querySelectorAll" in elem ) {
return elem.querySelectorAll( "*" );

} else {
return [];
}
}

jQuery.extend({ jQuery.extend({
clone: function( elem, dataAndEvents, deepDataAndEvents ) { clone: function( elem, dataAndEvents, deepDataAndEvents ) {
var clone = elem.cloneNode(true), var clone = elem.cloneNode(true),
srcElements, srcElements,
destElements, destElements,
i; i;


if ( !jQuery.support.noCloneEvent && (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
// IE copies events bound via attachEvent when using cloneNode. // IE copies events bound via attachEvent when using cloneNode.
// Calling detachEvent on the clone will also remove the events // Calling detachEvent on the clone will also remove the events
// from the original. In order to get around this, we use some // from the original. In order to get around this, we use some
Expand All @@ -507,8 +520,8 @@ jQuery.extend({


// Using Sizzle here is crazy slow, so we use getElementsByTagName // Using Sizzle here is crazy slow, so we use getElementsByTagName
// instead // instead
srcElements = elem.getElementsByTagName("*"); srcElements = getAll( elem );
destElements = clone.getElementsByTagName("*"); destElements = getAll( clone );


// Weird iteration because IE will replace the length property // Weird iteration because IE will replace the length property
// with an element if you are cloning the body and one of the // with an element if you are cloning the body and one of the
Expand All @@ -520,21 +533,18 @@ jQuery.extend({


// Copy the events from the original to the clone // Copy the events from the original to the clone
if ( dataAndEvents ) { if ( dataAndEvents ) {

cloneCopyEvent( elem, clone ); cloneCopyEvent( elem, clone );


if ( deepDataAndEvents && "getElementsByTagName" in elem ) { if ( deepDataAndEvents ) {

srcElements = getAll( elem );
srcElements = elem.getElementsByTagName("*"); destElements = getAll( clone );
destElements = clone.getElementsByTagName("*");


if ( srcElements.length ) { for ( i = 0; srcElements[i]; ++i ) {
for ( i = 0; srcElements[i]; ++i ) { cloneCopyEvent( srcElements[i], destElements[i] );
cloneCopyEvent( srcElements[i], destElements[i] );
}
} }
} }
} }

// Return the cloned set // Return the cloned set
return clone; return clone;
}, },
Expand Down
9 changes: 7 additions & 2 deletions src/support.js
Expand Up @@ -12,7 +12,8 @@
var all = div.getElementsByTagName("*"), var all = div.getElementsByTagName("*"),
a = div.getElementsByTagName("a")[0], a = div.getElementsByTagName("a")[0],
select = document.createElement("select"), select = document.createElement("select"),
opt = select.appendChild( document.createElement("option") ); opt = select.appendChild( document.createElement("option") ),
input = div.getElementsByTagName("input")[0];


// Can't get basic test support // Can't get basic test support
if ( !all || !all.length || !a ) { if ( !all || !all.length || !a ) {
Expand Down Expand Up @@ -51,7 +52,7 @@
// Make sure that if no value is specified for a checkbox // Make sure that if no value is specified for a checkbox
// that it defaults to "on". // that it defaults to "on".
// (WebKit defaults to "" instead) // (WebKit defaults to "" instead)
checkOn: div.getElementsByTagName("input")[0].value === "on", checkOn: input.value === "on",


// Make sure that a selected-by-default option has a working selected property. // Make sure that a selected-by-default option has a working selected property.
// (WebKit defaults to false instead of true, IE too, if it's in an optgroup) // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
Expand All @@ -62,12 +63,16 @@
optDisabled: false, optDisabled: false,
checkClone: false, checkClone: false,
noCloneEvent: true, noCloneEvent: true,
noCloneChecked: true,
boxModel: null, boxModel: null,
inlineBlockNeedsLayout: false, inlineBlockNeedsLayout: false,
shrinkWrapBlocks: false, shrinkWrapBlocks: false,
reliableHiddenOffsets: true reliableHiddenOffsets: true
}; };


input.checked = true;
jQuery.support.noCloneChecked = input.cloneNode( true ).checked;

// Make sure that the options inside disabled selects aren't marked as disabled // Make sure that the options inside disabled selects aren't marked as disabled
// (WebKit marks them as diabled) // (WebKit marks them as diabled)
select.disabled = true; select.disabled = true;
Expand Down
7 changes: 4 additions & 3 deletions test/unit/manipulation.js
Expand Up @@ -402,15 +402,16 @@ test("append(Function) with incoming value", function() {
}); });


test("append the same fragment with events (Bug #6997, 5566)", function () { test("append the same fragment with events (Bug #6997, 5566)", function () {
expect(2 + (document.fireEvent ? 1 : 0)); var doExtra = !jQuery.support.noCloneEvent && document.fireEvent;
expect(2 + (doExtra ? 1 : 0));
stop(1000); stop(1000);


var element; var element;


// This patch modified the way that cloning occurs in IE; we need to make sure that // This patch modified the way that cloning occurs in IE; we need to make sure that
// native event handlers on the original object don't get disturbed when they are // native event handlers on the original object don't get disturbed when they are
// modified on the clone // modified on the clone
if (!jQuery.support.noCloneEvent && document.fireEvent) { if ( doExtra ) {
element = jQuery("div:first").click(function () { element = jQuery("div:first").click(function () {
ok(true, "Event exists on original after being unbound on clone"); ok(true, "Event exists on original after being unbound on clone");
jQuery(this).unbind('click'); jQuery(this).unbind('click');
Expand Down Expand Up @@ -1015,7 +1016,7 @@ test("clone(form element) (Bug #3879, #6655)", function() {


equals( clone.is(":checked"), element.is(":checked"), "Checked input cloned correctly" ); equals( clone.is(":checked"), element.is(":checked"), "Checked input cloned correctly" );
equals( clone[0].defaultValue, "foo", "Checked input defaultValue cloned correctly" ); equals( clone[0].defaultValue, "foo", "Checked input defaultValue cloned correctly" );
equals( clone[0].defaultChecked, !jQuery.support.noCloneEvent, "Checked input defaultChecked cloned correctly" ); equals( clone[0].defaultChecked, !jQuery.support.noCloneChecked, "Checked input defaultChecked cloned correctly" );


element = jQuery("<input type='text' value='foo'>"); element = jQuery("<input type='text' value='foo'>");
clone = element.clone(); clone = element.clone();
Expand Down

0 comments on commit 292acd9

Please sign in to comment.