From 0a0cff9d29c4bd559da689d96c532d06c03fce09 Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Fri, 28 Jan 2011 10:55:39 -0600 Subject: [PATCH] Use the original element/fragment as the last item to be appended to the document instead of the first in order to prevent missing elements when appending to multiple elements. Fixes #8070. --- src/manipulation.js | 19 +++++++++++++------ test/unit/manipulation.js | 13 +++++++++++++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/manipulation.js b/src/manipulation.js index b7f2d3e..442a14d 100644 --- a/src/manipulation.js +++ b/src/manipulation.js @@ -186,7 +186,7 @@ jQuery.fn.extend({ clone: function( dataAndEvents, deepDataAndEvents ) { dataAndEvents = dataAndEvents == null ? true : dataAndEvents; deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - + return this.map( function () { return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); }); @@ -311,12 +311,19 @@ jQuery.fn.extend({ if ( first ) { table = table && jQuery.nodeName( first, "tr" ); - for ( var i = 0, l = this.length; i < l; i++ ) { + for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) { callback.call( table ? root(this[i], first) : this[i], - i > 0 || results.cacheable || (this.length > 1 && i > 0) ? + // Make sure that we do not leak memory by inadvertently discarding + // the original fragment (which might have attached data) instead of + // using it; in addition, use the original fragment object for the last + // item instead of first because it can end up being emptied incorrectly + // in certain situations (Bug #8070). + // Fragments from the fragment cache must always be cloned and never used + // in place. + results.cacheable || (l > 1 && i < lastIndex) ? jQuery.clone( fragment, true, true ) : fragment ); @@ -484,9 +491,9 @@ jQuery.each({ jQuery.extend({ clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var clone = elem.cloneNode(true), - srcElements, - destElements, + var clone = elem.cloneNode(true), + srcElements, + destElements, i; if ( !jQuery.support.noCloneEvent && (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js index 739868b..f0e2eae 100644 --- a/test/unit/manipulation.js +++ b/test/unit/manipulation.js @@ -883,6 +883,19 @@ test("jQuery.clone() (#8017)", function() { equals( main.childNodes.length, clone.childNodes.length, "Simple child length to ensure a large dom tree copies correctly" ); }); +test("clone() (#8070)", function () { + expect(2); + + jQuery('').appendTo('#main'); + var selects = jQuery('.test8070'); + selects.append(''); + + equals( selects[0].childNodes.length, 2, "First select got two nodes" ); + equals( selects[1].childNodes.length, 2, "Second select got two nodes" ); + + selects.remove(); +}); + test("clone()", function() { expect(37); equals( 'This is a normal link: Yahoo', jQuery('#en').text(), 'Assert text for #en' ); -- 1.7.10.4