2

I would like to convert the following string to DOM structure.

text node <div>div node</div>text node<p>paraph node</p> text node

One approach is,

mydiv = document.createElement('div');
mydiv.innerHTML = 'text node <div>div node</div>text node<p>paraph node</p> text node';

In this approach, the DOM structure is wrapped by another div, which is not i wanted.

After do searching and reading, I found document.createDocumentFragment() is the best way, because when append a fragment to node, it just append fragment's childNodes, not fragment itself

unfortunately, innerHTML method is not available in a fragment.

what should i do? thanks

4 Answers 4

8

Try this:

var frag = document.createDocumentFragment();
var mydiv = document.createElement('div');
mydiv.innerHTML = 'text node <div>div node</div>text node<p>paraph node</p> text node';


while( mydiv.firstChild ) {
    frag.appendChild( mydiv.firstChild );
}

document.body.appendChild( frag );
Sign up to request clarification or add additional context in comments.

2 Comments

Good one, check firstElementChild also.
This cuts the node from its origin, what about if i want to copy instead?
5

I tried all the solutions on this page and none were working sufficiently for my case (a more complex HTML string). I ended using this very simple approach with insertAdjacentHTML that I found here: https://stackoverflow.com/a/7327125/388412

div.insertAdjacentHTML( 'beforeend', str );

Comments

1

Esailija's answer will work cross-browser and in most situations and is what I'd favour in general, for now. Another option designed for precisely this task is the createContextualFragment() method of Range (see also DOM Parsing and Serialization spec). The idea is that it will create a DocumentFragment for the specified HTML string that is relevant to the location in the document represented by the start of a Range. Unfortunately, this method is not supported in IE <= 9, although IE 10 will support it.

Here's an example. Let's assume you're planning to insert the fragment at the end of the body:

var html = "text node <div>div node</div>text node<p>paraph node</p> text node";
var range = document.createRange();
range.selectNodeContents(document.body);
range.collapse(false);
var frag = range.createContextualFragment(html);

document.body.appendChild( frag );

2 Comments

createContextualFragment is the best way to convert string to DOM nodes. mydiv.firstChild is tricky, you have to loop all the nodes in mydiv which lose performance.Thanks for your great answer
@wukong no, you will only have to loop the immediate children of mydiv, not all nodes. And the performance difference is equal or negligible at best, completely irrelevant at worst because drawing the graphics on the screen is the bottleneck.
0

Okay, i just combine Tim's answer and Esailija's answer to one single function for convennience.

   function createDocumentFragment (inMarkup) {

        var range, fragment, dummy, elem;

        if (document.createRange && (range = document.createRange())
                && range.selectNodeContents
                && range.createContextualFragment) {

            range.collapse(false);

            range.selectNodeContents(document.body);

            fragment = range.createContextualFragment(inMarkup);

        } else {

            dummy = document.createElement('div');

            fragment = document.createDocumentFragment();

            dummy.innerHTML = inMarkup;

            while((elem = dummy.firstChild)) {

                fragment.appendChild(elem);

            }

        }

        return fragment;

    }

5 Comments

I'd recommend just using a battle tested library such as jQuery for this.
@Esailija: I wouldn't. jQuery does nothing with createContextualFragment() and your answer does the job fine.
@TimDown Not sure what you mean with "jQuery does nothing with createContextualFragment()" as jQuery doesn't use it all. By battle tested I meant that this code(and mine) will have tons of bugs that jQuery's buildFragment doesn't.
@Esailija: Yes, that was what I meant about createContextualFragment(). Re. jQuery's buildFragment(), you may be right. I haven't looked into it deeply and there seems to be no documentation on it whatsoever on the jQuery site.
@TimDown It's not documented because its meant for internal use only. There is no need for explicit use of fragments anyway if you are using jQuery/remotely decent dom library. But if you read the source for $.buildFragment and $.clean, you can easily see that we are reinventing square wheels here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.