1 2 3 4 5 6 7 8 9
> d = document.createElement('div') <div></div> > d.innerHTML = '<tr></tr>' "<tr></tr>" > d.innerHTML "" // ^^ Uh oh. Where'd it go?
The problem is that the
tag in HTML requires a parent of
, according to the
W3C HTML5 spec.
What this means is that in HTML a
is never a child of a
tag, and the browser automatically fixes this for you.
The jQuery and Knockout parsers get around this by wrapping the HTML in the
parent nodes that are required. There are a few HTML elements that need
parents of a specific sort:
Two popular parsing implementations, jQuery and Knockout, have problems.
jQuery v1.11.3 and v2.1.4 incorrectly parse custom elements that start with one
of the nodes that requires wrapping, such as
The Knockout 3.3.0
parser has trouble with comments that precede an element such as
. (Though we are working to fix this!)
<!-- ... --><b>...
These problems with
are edge cases, but they can be
difficult to debug and onerous to work around.
An elegant – and arguably the “correct” – answer becomes available when a
browser supports the
tag. Let’s have a look at the example above,
but using a template tag:
1 2 3 4 5 6 7 8 9
> t = document.createElement('template') <template>…</template> > t.innerHTML = '<tr></tr>' "<tr></tr>" > t.innerHTML "<tr></tr>" // ^^ Happy dance?
This works because the template tag spec permits its content to be nodes of any of the elements that require us working around.
You can get the parsed nodes by iterating over
(if you want HTML comments and text nodes) or
(if you do not).
You can also inject the parsed content into the document as follows, but bear in
mind that the parental rule requirements apply after insertion.
var clone = document.importNode(t.content, true); document.body.appendChild(clone);
The result is that you have access to the browser’s native HTML parsing, without those relatively complex (and possibly slow) workarounds that aspire to but do not quite reach parity with builtin browser parser.