8

I'm playing around with a document fragment. I find it hard to understand how it behave when I append it to the DOM.

I create a doc fragment that I assign to a variable, when I insert some stuff into it, and append the doc fragment into a element. But if I clear the element my variable which should reference to the doc fragment contain an empty document fragment.

I trying to make a cache for a third party lib that creates document fragments. So I would like to get this working. Should I create a cloneNode before I append the fragment to the DOM, is that correct?

I have created a JS fiddle: http://jsfiddle.net/4CTXG/1/

var test = document.createDocumentFragment();
//var test = document.createElement("div"); // This one work

$(test).append($("<div>").html('Hello world!'));


$("#result").append(test);

setTimeout(function(){
    $("#result").children().remove();   
    $("#result").append(test);

    console.log('Now test should have been appended');
    $(result).css({"background": "#FF0000"});
},5000)
Simon Edström
  • 6,461
  • 7
  • 32
  • 52

2 Answers2

15

When you append an Element (e.g. the <div>) into the DOM, the Element gets added as a child of its new parent. The div's children are not changed. When you remove the element from its parent, the Element is just detached from the DOM. It you still have a reference to the Element it will still contain its children, available to reattach later.

When you append an DocumentFragment into the DOM, the children of the DocumentFragment are removed from the DocumentFragment and moved to be children of its DOM element parent. The DocumentFragment is now empty.

So instead of appending the DocumentFragment, you should append a deep clone of the fragment.

See http://dom.spec.whatwg.org/#concept-node-insert for the gory details.

Alohci
  • 78,296
  • 16
  • 112
  • 156
  • For example `myElement.appendChild(myFragment.cloneNode(true))` does indeed work, but the `myFragment` clone's child nodes are clones too, so, if you select a child node of the original `myFragment`, that is *not* the same node that is added to the DOM. Is that correct? – djvg Sep 15 '21 at 09:19
-2

Javascript objects are copied by reference rather than value. So when you assign the fragment to a variable and then insert the fragment into the DOM, both the variable and the DOM are referencing the same object. Any change you make to one will also occur in the other.

If you really want the variable to reference an object that is distinct from the DOM, then cloning is the right approach.

Stephen Thomas
  • 13,843
  • 2
  • 32
  • 53
  • But why is it wokring with createElement? And why is it erased? – Simon Edström Aug 14 '13 at 12:14
  • Because [createDocumentFragment()](https://developer.mozilla.org/en-US/docs/Web/API/document.createDocumentFragment) returns an object, while [createElement()](https://developer.mozilla.org/en-US/docs/Web/API/document.createElement) returns an HTML element. – Stephen Thomas Aug 14 '13 at 12:17
  • Ok, make sense thanks. Is it possible to remove the document fragment from the DOM without erase it? – Simon Edström Aug 14 '13 at 12:19
  • See this [answer](http://stackoverflow.com/questions/8830839/javascript-dom-remove-element) – Stephen Thomas Aug 14 '13 at 12:20
  • @StephenThomas That is not true, both DocumentFragment and HTMLElement are objects that inherit from Node. – losnir Jul 23 '15 at 16:43
  • 1
    @SimonEdström The createElement approach is working for you since appending an HTMLElement to the DOM, keeps the original reference, whereas appending a DocumentFragment *moves* it's children to the DOM, and then erases the DocumentFragment itself. – losnir Jul 23 '15 at 16:46