How to capture innerHTML from a documentFragment via Javascript?

Asked

Viewed 629 times

2

The documentFragmentwhich is created using the document.createDocumentFragment() does not contain the properties innerHTML and outerHTML equal elements derived from HTMLElement has.

But I need to take the contents of the fragment in string format. However I can’t just give a appendChild of the fragment in another element to have the innerHTML, because this would leave the instance of the fragment empty once its contents would be transported to another element.

I need to extract the HTML in string form from the fragment without changing it.

3 answers

2


Use only: frag.querySelector('*').innerHTML

The asterisk selects any first DOM object found within the fragment, which in this case is the root, and then with the root DOM object in the hands it is possible to use innerHTML, or the outerHTML if applicable.

EDIT

In case your fragment contains multiple root elements, then use querySelectorAll:

var conteudo = "";
var all = frag.querySelectorAll('*');
    for (var i = 0; i < all.length; i++)
        if (!all[i].parentElement)
            conteudo += all[i].outerHTML;

// mostrando o output na página
$("#output").text($("#output").text() + conteudo);

querySelectorAll is well supported in browsers: http://caniuse.com/queryselector

EDIT 2: A more performative solution using querySelector instead of querySelectorAll:

var conteudo = "";
var current = frag.querySelector('*');
while (current) {
    conteudo += current.outerHTML + "\n";
    current = current.nextSibling;
}

EDIT 3: since the previous options didn’t work in IE8, I kept looking until I found the following alternative (which works on all browsers I tested):

var conteudo = "";
var rootNodes = frag.childNodes;
for (var i = 0; i < rootNodes.length; i++)
    conteudo += rootNodes[i].outerHTML;
  • I updated the answer to multiple root elements.

  • querySelectorAll guarantees the order of the elements? If it guarantees probably this solution this solution serves my purpose.

  • Gosh, he’s also selecting the children... I’ll see if there’s only the root elements without the children.

  • Miguel I think that to join your answer with bfavaretto, would be the most correct solution, now I do not know who to give as solution to the question...

  • I think that querySelectorAll('*') will catch all the elements inside the Fragment, not just the roots.

  • Corrected code, now only the roots will be selected.

  • I deleted the non-roots manually, inside the for... I don’t know if this is good for performance.

  • Now yes, a solution that is not bad performance: use querySelector('*') and then use nextSibling and concatenate the outerHTML. This way, even, the ordering is more guaranteed... is the order of insertion of the elements in the fragment.

  • Thousandth edition... =) It was bad for so many personal editions.

  • 1

    Thanks Miguel, really the last was the same thing I ended up doing to solve this case, so the answer is correct, the cool of the issues is that there is a knowledge base for the next ones who have this same doubt. = ) Thank you again!

  • Edit 2 is very efficient, 3x faster than mine: http://jsperf.com/documentfragment-innerhtml

Show 6 more comments

1

Considering your requirements, it seems the only way would be to clone each fragment’s child:

function fragHtml(frag) {
    var div = document.createElement('div');
    for(var i=0; i<frag.children.length; i++) {
        div.appendChild(frag.children[i].cloneNode(true));
    }
    return div.innerHTML;
}
  • Very interesting, but I think that to get the string, the best solution should be to join your answer with Miguel Angelo’s, because your solution keeps the order of the elements correct, just do not need to clone all elements to get your string...

1

To MDN refers the method:

element = documentframgment.querySelector(selectors);

So an example would be:

HTML

<div id="test" contenteditable="true">
    Teste
    <img src="/favicon.png" alt=""/>
</div>

JS

var frag = document.createDocumentFragment();
var teste = document.getElementById('test');
frag.appendChild(teste);
console.log(frag);       // #document-fragment
var conteudo = frag.querySelector('#test');
console.log(conteudo.innerHTML);   //  Teste<img src="/favicon.png" alt="">

Example

Browser other questions tagged

You are not signed in. Login or sign up in order to post.