I know that adding innerHTML
to document fragments has been recently discussed, and will hopefully see inclusion in the DOM Standard. But, what is the workaround you're supposed to use in the meantime?
That is, take
var html = '<div>x</div><span>y</span>';
var frag = document.createDocumentFragment();
I want both the div
and the span
inside of frag
, with an easy one-liner.
Bonus points for no loops. jQuery is allowed, but I've already tried $(html).appendTo(frag)
; frag
is still empty afterward.
Here is a way in modern browsers without looping:
var temp = document.createElement('template');
temp.innerHTML = '<div>x</div><span>y</span>';
var frag = temp.content;
or, as a re-usable
function fragmentFromString(strHTML) {
var temp = document.createElement('template');
temp.innerHTML = strHTML;
return temp.content;
}
UPDATE: I found a simpler way to use Pete's main idea, which adds IE11 to the mix:
function fragmentFromString(strHTML) {
return document.createRange().createContextualFragment(strHTML);
}
The coverage is better than the <template>
method and tested ok in IE11, Ch, FF.
Live test/demo available http://pagedemos.com/str2fragment/
Currently, the only way to fill a document fragment using only a string is to create a temporary object, and loop through the children to append them to the fragment.
If you want to create a whole document, use the DOMParser instead. Have a look at this answer.
Code:
var frag = document.createDocumentFragment(),
tmp = document.createElement('body'), child;
tmp.innerHTML = '<div>x</div><span>y</span>';
while (child = tmp.firstElementChild) {
frag.appendChild(child);
}
A one-liner (two lines for readability) (input: String html
, output: DocumentFragment frag
):
var frag =document.createDocumentFragment(), t=document.createElement('body'), c;
t.innerHTML = html; while(c=t.firstElementChild) frag.appendChild(c);
Use Range.createContextualFragment:
var html = '<div>x</div><span>y</span>';
var range = document.createRange();
// or whatever context the fragment is to be evaluated in.
var parseContext = document.body;
range.selectNodeContents(parseContext);
var fragment = range.createContextualFragment(html);
Note that the primary differences between this approach and the <template>
approach are:
Range.createContextualFragment is a bit more widely supported (IE11 just got it, Safari, Chrome and FF have had it for a while).
Custom elements within the HTML will be upgraded immediately with the range, but only when cloned into the real doc with template. The template approach is a bit more 'inert', which may be desirable.
No one ever provided the requested "easy one-liner".
Given the variables…
var html = '<div>x</div><span>y</span>';
var frag = document.createDocumentFragment();
… the following line will do the trick (in Firefox 67.0.4):
frag.append(...new DOMParser().parseFromString(html, "text/html").body.childNodes);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With