diff --git a/src/manipulation.js b/src/manipulation.js index ce05fd63c..984f80307 100644 --- a/src/manipulation.js +++ b/src/manipulation.js @@ -33,7 +33,7 @@ var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figca legend: [ 1, "
" ], area: [ 1, "" ], param: [ 1, "" ], - thead: [ 1, "" ], + thead: [ 1, "
" ], tr: [ 2, "
" ], col: [ 2, "
", "
" ], td: [ 3, "" ], @@ -308,9 +308,8 @@ jQuery.fn.extend({ }); } - if ( this[0] ) { - doc = this[0].ownerDocument; - fragment = jQuery.buildFragment( args, doc, false, this ); + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); first = fragment.firstChild; if ( fragment.childNodes.length === 1 ) { @@ -619,21 +618,20 @@ jQuery.extend({ }, buildFragment: function( elems, context, scripts, selection ) { - var elem, j, tmp, tag, wrap, tbody, - nodes = [], - i = 0, + var contains, elem, tag, tmp, wrap, tbody, j, l = elems.length, - fragment = context.createDocumentFragment(), - safe = context === document && safeFragment; - // Ensure that context is a document - if ( !context || typeof context.createDocumentFragment === "undefined" ) { - context = document; - } + // Ensure a safe fragment + safe = createSafeFragment( context ), + + nodes = [], + i = 0; for ( ; i < l; i++ ) { elem = elems[ i ]; + if ( elem || elem === 0 ) { + // Add nodes directly if ( jQuery.type( elem ) === "object" ) { jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); @@ -644,8 +642,6 @@ jQuery.extend({ // Convert html into DOM nodes } else { - // Ensure a safe container - safe = safe || createSafeFragment( context ); tmp = tmp || safe.appendChild( context.createElement("div") ); // Deserialize a standard representation @@ -700,7 +696,7 @@ jQuery.extend({ } } - // Fix #11356: Clear elements from safeFragment + // Fix #11356: Clear elements from fragment if ( tmp ) { safe.removeChild( tmp ); } @@ -713,18 +709,20 @@ jQuery.extend({ i = 0; while ( (elem = nodes[ i++ ]) ) { - safe = jQuery.contains( elem.ownerDocument, elem ); + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); // Append to fragment - // #4087 - If origin and destination elements are the same, and this is - // that element, do not append to fragment - if ( !selection || jQuery.inArray( elem, selection ) === -1 ) { - fragment.appendChild( elem ); - } - tmp = getAll( elem, "script" ); + tmp = getAll( safe.appendChild( elem ), "script" ); // Preserve script evaluation history - if ( safe ) { + if ( contains ) { setGlobalEval( tmp ); } @@ -739,9 +737,9 @@ jQuery.extend({ } } - elem = tmp = safe = null; + tmp = null; - return fragment; + return safe; }, cleanData: function( elems, /* internal */ acceptData ) { diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js index 74e482a47..1d95a73d7 100644 --- a/test/unit/manipulation.js +++ b/test/unit/manipulation.js @@ -395,13 +395,13 @@ var testAppendForObject = function( valueObj, isFragment ) { var testAppend = function( valueObj ) { - expect( 60 ); + expect( 78 ); testAppendForObject( valueObj, false ); testAppendForObject( valueObj, true ); var defaultText, result, message, iframe, iframeDoc, j, d, - $input, $radioChecked, $radioUnchecked, $radioParent; + $input, $radioChecked, $radioUnchecked, $radioParent, $map, $table; defaultText = "Try them out:"; result = jQuery("#first").append( valueObj("buga") ); @@ -446,18 +446,29 @@ var testAppend = function( valueObj ) { jQuery("
").appendTo("#form").append( valueObj("test") ); t( "Append legend", "#legend", [ "legend" ] ); + $map = jQuery("").append( valueObj("jQuery") ); + + equal( $map[ 0 ].childNodes.length, 1, "The area was inserted." ); + equal( $map[ 0 ].firstChild.nodeName.toLowerCase(), "area", "The area was inserted." ); + jQuery("#select1").append( valueObj("") ); equal( jQuery("#select1 option:last").text(), "Test", "Appending OPTION (all caps)" ); - jQuery("#table").append( valueObj("
") ); - equal( jQuery("#table colgroup").length, 1, "Append colgroup" ); + jQuery("#select1").append( valueObj("") ); + equal( jQuery("#select1 optgroup").attr("label"), "optgroup", "Label attribute in newly inserted optgroup is correct" ); + equal( jQuery("#select1 option:last").text(), "optgroup", "Appending optgroup" ); + + $table = jQuery("#table").empty(); + + jQuery.each( "thead tbody tfoot colgroup caption tr th td".split(" "), function( i, name ) { + $table.append( valueObj( "<" + name + "/>" ) ); + ok( $table.find( name ).length >= 1, "Append " + name ); + ok( jQuery.parseHTML( "<" + name + "/>" ).length, name + " wrapped correctly" ); + }); jQuery("#table colgroup").append( valueObj("") ); equal( jQuery("#table colgroup col").length, 1, "Append col" ); - jQuery("#table").append( valueObj("") ); - equal( jQuery("#table caption").length, 1, "Append caption" ); - jQuery("#form") .append( valueObj("") ) .append( valueObj("") ); @@ -2229,9 +2240,19 @@ test( "insertAfter, insertBefore, etc do not work when destination is original e }); test( "Index for function argument should be received (#13094)", 2, function() { - var i = 0; + var i = 0; + + jQuery("
").before(function( index ) { + equal( index, i++, "Index should be correct" ); + }); - jQuery("
").before(function( index ) { - equal( index, i++, "Index should be correct" ); - }); +}); + +test( "Make sure jQuery.fn.remove can work on elements in documentFragment", 1, function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement("div") ); + + jQuery( div ).remove(); + + equal( fragment.childNodes.length, 0, "div element was removed from documentFragment" ); });