[javascript] Creating a new DOM element from an HTML string using built-in DOM methods or Prototype

I have an HTML string representing an element: '<li>text</li>'. I'd like to append it to an element in the DOM (a ul in my case). How can I do this with Prototype or with DOM methods?

(I know i could do this easily in jQuery, but unfortunately we're not using jQuery.)

This question is related to javascript dom prototypejs

The answer is


Newer DOM implementations have range.createContextualFragment, which does what you want in a framework-independent way.

It's widely supported. To be sure though, check its compatibility down in the same MDN link, as it will be changing. As of May 2017 this is it:

Feature         Chrome   Edge   Firefox(Gecko)  Internet Explorer   Opera   Safari
Basic support   (Yes)    (Yes)  (Yes)           11                  15.0    9.1.2

This will work too:

$('<li>').text('hello').appendTo('#mylist');

It feels more like a jquery way with the chained function calls.


You can create valid DOM nodes from a string using:

document.createRange().createContextualFragment()

The following example adds a button element in the page taking the markup from a string:

_x000D_
_x000D_
let html = '<button type="button">Click Me!</button>';_x000D_
let fragmentFromString = function (strHTML) {_x000D_
  return document.createRange().createContextualFragment(strHTML);_x000D_
}_x000D_
let fragment = fragmentFromString(html);_x000D_
document.body.appendChild(fragment);
_x000D_
_x000D_
_x000D_


I added a Document prototype that creates an element from string:

Document.prototype.createElementFromString = function (str) {
    const element = new DOMParser().parseFromString(str, 'text/html');
    const child = element.documentElement.querySelector('body').firstChild;
    return child;
};

For the heck of it I thought I'd share this over complicated but yet simple approach I came up with... Maybe someone will find something useful.

/*Creates a new element - By Jamin Szczesny*/
function _new(args){
    ele = document.createElement(args.node);
    delete args.node;
    for(x in args){ 
        if(typeof ele[x]==='string'){
            ele[x] = args[x];
        }else{
            ele.setAttribute(x, args[x]);
        }
    }
    return ele;
}

/*You would 'simply' use it like this*/

$('body')[0].appendChild(_new({
    node:'div',
    id:'my-div',
    style:'position:absolute; left:100px; top:100px;'+
          'width:100px; height:100px; border:2px solid red;'+
          'cursor:pointer; background-color:HoneyDew',
    innerHTML:'My newly created div element!',
    value:'for example only',
    onclick:"alert('yay')"
}));

No need for any tweak, you got a native API:

const toNodes = html =>
    new DOMParser().parseFromString(html, 'text/html').body.childNodes[0]

var jtag = $j.li({ child:'text' }); // Represents: <li>text</li>
var htmlContent = $('mylist').html();
$('mylist').html(htmlContent + jtag.html());

Use jnerator


function domify (str) {
  var el = document.createElement('div');
  el.innerHTML = str;

  var frag = document.createDocumentFragment();
  return frag.appendChild(el.removeChild(el.firstChild));
}

var str = "<div class='foo'>foo</div>";
domify(str);

I am using this method (Works in IE9+), although it will not parse <td> or some other invalid direct childs of body:

function stringToEl(string) {
    var parser = new DOMParser(),
        content = 'text/html',
        DOM = parser.parseFromString(string, content);

    // return element
    return DOM.body.childNodes[0];
}

stringToEl('<li>text</li>'); //OUTPUT: <li>text</li>

Fastest solution to render DOM from string:

let render = (relEl, tpl, parse = true) => {
  if (!relEl) return;
  const range = document.createRange();
  range.selectNode(relEl);
  const child = range.createContextualFragment(tpl);
  return parse ? relEl.appendChild(child) : {relEl, el};
};

And here u can check performance for DOM manipulation React vs native JS

Now u can simply use:

let element = render(document.body, `
<div style="font-size:120%;line-height:140%">
  <p class="bold">New DOM</p>
</div>
`);

And of course in near future u use references from memory cause var "element" is your new created DOM in your document.

And remember "innerHTML=" is very slow :/


Newer DOM implementations have range.createContextualFragment, which does what you want in a framework-independent way.

It's widely supported. To be sure though, check its compatibility down in the same MDN link, as it will be changing. As of May 2017 this is it:

Feature         Chrome   Edge   Firefox(Gecko)  Internet Explorer   Opera   Safari
Basic support   (Yes)    (Yes)  (Yes)           11                  15.0    9.1.2

I am using this method (Works in IE9+), although it will not parse <td> or some other invalid direct childs of body:

function stringToEl(string) {
    var parser = new DOMParser(),
        content = 'text/html',
        DOM = parser.parseFromString(string, content);

    // return element
    return DOM.body.childNodes[0];
}

stringToEl('<li>text</li>'); //OUTPUT: <li>text</li>

HTML5 & ES6

<template>

Demo

_x000D_
_x000D_
"use strict";_x000D_
_x000D_
/**_x000D_
 *_x000D_
 * @author xgqfrms_x000D_
 * @license MIT_x000D_
 * @copyright xgqfrms_x000D_
 * @description HTML5 Template_x000D_
 * @augments_x000D_
 * @example_x000D_
 *_x000D_
 */_x000D_
_x000D_
/*_x000D_
_x000D_
<template>_x000D_
    <h2>Flower</h2>_x000D_
    <img src="https://www.w3schools.com/tags/img_white_flower.jpg">_x000D_
</template>_x000D_
_x000D_
_x000D_
<template>_x000D_
    <div class="myClass">I like: </div>_x000D_
</template>_x000D_
_x000D_
*/_x000D_
_x000D_
const showContent = () => {_x000D_
    // let temp = document.getElementsByTagName("template")[0],_x000D_
    let temp = document.querySelector(`[data-tempalte="tempalte-img"]`),_x000D_
        clone = temp.content.cloneNode(true);_x000D_
    document.body.appendChild(clone);_x000D_
};_x000D_
_x000D_
const templateGenerator = (datas = [], debug = false) => {_x000D_
    let result = ``;_x000D_
    // let temp = document.getElementsByTagName("template")[1],_x000D_
    let temp = document.querySelector(`[data-tempalte="tempalte-links"]`),_x000D_
        item = temp.content.querySelector("div");_x000D_
    for (let i = 0; i < datas.length; i++) {_x000D_
        let a = document.importNode(item, true);_x000D_
        a.textContent += datas[i];_x000D_
        document.body.appendChild(a);_x000D_
    }_x000D_
    return result;_x000D_
};_x000D_
_x000D_
const arr = ["Audi", "BMW", "Ford", "Honda", "Jaguar", "Nissan"];_x000D_
_x000D_
if (document.createElement("template").content) {_x000D_
    console.log("YES! The browser supports the template element");_x000D_
    templateGenerator(arr);_x000D_
    setTimeout(() => {_x000D_
        showContent();_x000D_
    }, 0);_x000D_
} else {_x000D_
    console.error("No! The browser does not support the template element");_x000D_
}
_x000D_
@charset "UTf-8";_x000D_
_x000D_
/* test.css */_x000D_
_x000D_
:root {_x000D_
    --cololr: #000;_x000D_
    --default-cololr: #fff;_x000D_
    --new-cololr: #0f0;_x000D_
}_x000D_
_x000D_
[data-class="links"] {_x000D_
    color: white;_x000D_
    background-color: DodgerBlue;_x000D_
    padding: 20px;_x000D_
    text-align: center;_x000D_
    margin: 10px;_x000D_
}
_x000D_
<!DOCTYPE html>_x000D_
<html lang="zh-Hans">_x000D_
_x000D_
<head>_x000D_
    <meta charset="UTF-8">_x000D_
    <meta name="viewport" content="width=device-width, initial-scale=1.0">_x000D_
    <meta http-equiv="X-UA-Compatible" content="ie=edge">_x000D_
    <title>Template Test</title>_x000D_
    <!--[if lt IE 9]>_x000D_
        <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>_x000D_
    <![endif]-->_x000D_
</head>_x000D_
_x000D_
<body>_x000D_
    <section>_x000D_
        <h1>Template Test</h1>_x000D_
    </section>_x000D_
    <template data-tempalte="tempalte-img">_x000D_
        <h3>Flower Image</h3>_x000D_
        <img src="https://www.w3schools.com/tags/img_white_flower.jpg">_x000D_
    </template>_x000D_
    <template data-tempalte="tempalte-links">_x000D_
        <h3>links</h3>_x000D_
        <div data-class="links">I like: </div>_x000D_
    </template>_x000D_
    <!-- js -->_x000D_
</body>_x000D_
_x000D_
</html>
_x000D_
_x000D_
_x000D_


var jtag = $j.li({ child:'text' }); // Represents: <li>text</li>
var htmlContent = $('mylist').html();
$('mylist').html(htmlContent + jtag.html());

Use jnerator


For certain html fragments like <td>test</td>, div.innerHTML, DOMParser.parseFromString and range.createContextualFragment (without the right context) solutions mentioned in other answers here, won't create the <td> element.

jQuery.parseHTML() handles them properly (I extracted jQuery 2's parseHTML function into an independent function that can be used in non-jquery codebases).

If you are only supporting Edge 13+, it is simpler to just use the HTML5 template tag:

function parseHTML(html) {
    var t = document.createElement('template');
    t.innerHTML = html;
    return t.content.cloneNode(true);
}

var documentFragment = parseHTML('<td>Test</td>');

HTML 5 introduced the <template> element which can be used for this purpose (as now described in the WhatWG spec and MDN docs).

A <template> element is used to declare fragments of HTML that can be utilized in scripts. The element is represented in the DOM as a HTMLTemplateElement which has a .content property of DocumentFragment type, to provide access to the template's contents. This means that you can convert an HTML string to DOM elements by setting the innerHTML of a <template> element, then reaching into the template's .content property.

Examples:

/**
 * @param {String} HTML representing a single element
 * @return {Element}
 */
function htmlToElement(html) {
    var template = document.createElement('template');
    html = html.trim(); // Never return a text node of whitespace as the result
    template.innerHTML = html;
    return template.content.firstChild;
}

var td = htmlToElement('<td>foo</td>'),
    div = htmlToElement('<div><span>nested</span> <span>stuff</span></div>');

/**
 * @param {String} HTML representing any number of sibling elements
 * @return {NodeList} 
 */
function htmlToElements(html) {
    var template = document.createElement('template');
    template.innerHTML = html;
    return template.content.childNodes;
}

var rows = htmlToElements('<tr><td>foo</td></tr><tr><td>bar</td></tr>');

Note that similar approaches that use a different container element such as a div don't quite work. HTML has restrictions on what element types are allowed to exist inside which other element types; for instance, you can't put a td as a direct child of a div. This causes these elements to vanish if you try to set the innerHTML of a div to contain them. Since <template>s have no such restrictions on their content, this shortcoming doesn't apply when using a template.

However, template is not supported in some old browsers. As of January 2018, Can I use... estimates 90% of users globally are using a browser that supports templates. In particular, no version of Internet Explorer supports them; Microsoft did not implement template support until the release of Edge.

If you're lucky enough to be writing code that's only targeted at users on modern browsers, go ahead and use them right now. Otherwise, you may have to wait a while for users to catch up.


var msg = "test" jQuery.parseHTML(msg)


Why don't do with native js?

    var s="<span class='text-muted' style='font-size:.75em; position:absolute; bottom:3px; left:30px'>From <strong>Dan's Tools</strong></span>"
    var e=document.createElement('div')
    var r=document.createRange();
    r.selectNodeContents(e)
    var f=r.createContextualFragment(s);
    e.appendChild(f);
    e = e.firstElementChild;

Late but just as a note;

It's possible to add a trivial element to target element as a container and remove it after using.

// Tested on chrome 23.0, firefox 18.0, ie 7-8-9 and opera 12.11.

<div id="div"></div>

<script>
window.onload = function() {
    var foo, targetElement = document.getElementById('div')
    foo = document.createElement('foo')
    foo.innerHTML = '<a href="#" target="_self">Text of A 1.</a> '+
                    '<a href="#" onclick="return !!alert(this.innerHTML)">Text of <b>A 2</b>.</a> '+
                    '<hr size="1" />'
    // Append 'foo' element to target element
    targetElement.appendChild(foo)

    // Add event
    foo.firstChild.onclick = function() { return !!alert(this.target) }

    while (foo.firstChild) {
        // Also removes child nodes from 'foo'
        targetElement.insertBefore(foo.firstChild, foo)
    }
    // Remove 'foo' element from target element
    targetElement.removeChild(foo)
}
</script>

Here is working code for me

I wanted to convert 'Text' string to HTML element

var diva = UWA.createElement('div');
diva.innerHTML = '<a href="http://wwww.example.com">Text</a>';
var aelement = diva.firstChild;

This will work too:

$('<li>').text('hello').appendTo('#mylist');

It feels more like a jquery way with the chained function calls.


To enhance furthermore the useful .toDOM() snippet that we can find in different places, we can now safely use backticks (template literals).

So we can have single and double quotes in the foo html declaration.

This behave like heredocs for those familiar with the term.

This can be enhanced furthermore with variables, to make complex templating:

Template literals are enclosed by the back-tick () (grave accent) character instead of double or single quotes. Template literals can contain placeholders. These are indicated by the dollar sign and curly braces (${expression}). The expressions in the placeholders and the text between them get passed to a function. The default function just concatenates the parts into a single string. If there is an expression preceding the template literal (tag here), this is called a "tagged template". In that case, the tag expression (usually a function) gets called with the processed template literal, which you can then manipulate before outputting. To escape a back-tick in a template literal, put a backslash \ before the back-tick.

_x000D_
_x000D_
String.prototype.toDOM=function(){_x000D_
  var d=document,i_x000D_
     ,a=d.createElement("div")_x000D_
     ,b=d.createDocumentFragment()_x000D_
  a.innerHTML = this_x000D_
  while(i=a.firstChild)b.appendChild(i)_x000D_
  return b_x000D_
}_x000D_
_x000D_
// Using template litterals_x000D_
var a = 10, b = 5_x000D_
var foo=`_x000D_
<img _x000D_
  onclick="alert('The future start today!')"   _x000D_
  src='//placekitten.com/100/100'>_x000D_
foo${a + b}_x000D_
  <i>bar</i>_x000D_
    <hr>`.toDOM();_x000D_
document.body.appendChild(foo);
_x000D_
img {cursor: crosshair}
_x000D_
_x000D_
_x000D_

So, why not use directly .innerHTML +=? By doing so, the whole DOM is being recalculated by the browser, it's much slower.

https://caniuse.com/template-literals


HTML5 & ES6

<template>

Demo

_x000D_
_x000D_
"use strict";_x000D_
_x000D_
/**_x000D_
 *_x000D_
 * @author xgqfrms_x000D_
 * @license MIT_x000D_
 * @copyright xgqfrms_x000D_
 * @description HTML5 Template_x000D_
 * @augments_x000D_
 * @example_x000D_
 *_x000D_
 */_x000D_
_x000D_
/*_x000D_
_x000D_
<template>_x000D_
    <h2>Flower</h2>_x000D_
    <img src="https://www.w3schools.com/tags/img_white_flower.jpg">_x000D_
</template>_x000D_
_x000D_
_x000D_
<template>_x000D_
    <div class="myClass">I like: </div>_x000D_
</template>_x000D_
_x000D_
*/_x000D_
_x000D_
const showContent = () => {_x000D_
    // let temp = document.getElementsByTagName("template")[0],_x000D_
    let temp = document.querySelector(`[data-tempalte="tempalte-img"]`),_x000D_
        clone = temp.content.cloneNode(true);_x000D_
    document.body.appendChild(clone);_x000D_
};_x000D_
_x000D_
const templateGenerator = (datas = [], debug = false) => {_x000D_
    let result = ``;_x000D_
    // let temp = document.getElementsByTagName("template")[1],_x000D_
    let temp = document.querySelector(`[data-tempalte="tempalte-links"]`),_x000D_
        item = temp.content.querySelector("div");_x000D_
    for (let i = 0; i < datas.length; i++) {_x000D_
        let a = document.importNode(item, true);_x000D_
        a.textContent += datas[i];_x000D_
        document.body.appendChild(a);_x000D_
    }_x000D_
    return result;_x000D_
};_x000D_
_x000D_
const arr = ["Audi", "BMW", "Ford", "Honda", "Jaguar", "Nissan"];_x000D_
_x000D_
if (document.createElement("template").content) {_x000D_
    console.log("YES! The browser supports the template element");_x000D_
    templateGenerator(arr);_x000D_
    setTimeout(() => {_x000D_
        showContent();_x000D_
    }, 0);_x000D_
} else {_x000D_
    console.error("No! The browser does not support the template element");_x000D_
}
_x000D_
@charset "UTf-8";_x000D_
_x000D_
/* test.css */_x000D_
_x000D_
:root {_x000D_
    --cololr: #000;_x000D_
    --default-cololr: #fff;_x000D_
    --new-cololr: #0f0;_x000D_
}_x000D_
_x000D_
[data-class="links"] {_x000D_
    color: white;_x000D_
    background-color: DodgerBlue;_x000D_
    padding: 20px;_x000D_
    text-align: center;_x000D_
    margin: 10px;_x000D_
}
_x000D_
<!DOCTYPE html>_x000D_
<html lang="zh-Hans">_x000D_
_x000D_
<head>_x000D_
    <meta charset="UTF-8">_x000D_
    <meta name="viewport" content="width=device-width, initial-scale=1.0">_x000D_
    <meta http-equiv="X-UA-Compatible" content="ie=edge">_x000D_
    <title>Template Test</title>_x000D_
    <!--[if lt IE 9]>_x000D_
        <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>_x000D_
    <![endif]-->_x000D_
</head>_x000D_
_x000D_
<body>_x000D_
    <section>_x000D_
        <h1>Template Test</h1>_x000D_
    </section>_x000D_
    <template data-tempalte="tempalte-img">_x000D_
        <h3>Flower Image</h3>_x000D_
        <img src="https://www.w3schools.com/tags/img_white_flower.jpg">_x000D_
    </template>_x000D_
    <template data-tempalte="tempalte-links">_x000D_
        <h3>links</h3>_x000D_
        <div data-class="links">I like: </div>_x000D_
    </template>_x000D_
    <!-- js -->_x000D_
</body>_x000D_
_x000D_
</html>
_x000D_
_x000D_
_x000D_


Answer

  • Create a Template
  • Set the Template's innerHTML to your string .trim()
  • Create an Array of Template's children
  • Return children, child, or

_x000D_
_x000D_
function toElement(s='',c,t=document.createElement('template'),l='length'){
t.innerHTML=s.trim();c=[...t.content.childNodes];return c[l]>1?c:c[0]||'';}



console.log(toElement());
console.log(toElement(''));
console.log(toElement('    '));
console.log(toElement('<td>With td</td>'));
console.log(toElement('<tr><td>With t</td></tr>'));
console.log(toElement('<tr><td>foo</td></tr><tr><td>bar</td></tr>'));
console.log(toElement('<div><span>nested</span> <span>stuff</span></div>'));
_x000D_
_x000D_
_x000D_


I added a Document prototype that creates an element from string:

Document.prototype.createElementFromString = function (str) {
    const element = new DOMParser().parseFromString(str, 'text/html');
    const child = element.documentElement.querySelector('body').firstChild;
    return child;
};

With Prototype, you can also do:

HTML:

<ul id="mylist"></ul>

JS:

$('mylist').insert('<li>text</li>');

Why don't do with native js?

    var s="<span class='text-muted' style='font-size:.75em; position:absolute; bottom:3px; left:30px'>From <strong>Dan's Tools</strong></span>"
    var e=document.createElement('div')
    var r=document.createRange();
    r.selectNodeContents(e)
    var f=r.createContextualFragment(s);
    e.appendChild(f);
    e = e.firstElementChild;

With Prototype, you can also do:

HTML:

<ul id="mylist"></ul>

JS:

$('mylist').insert('<li>text</li>');

Here's my code, and it works:

function parseTableHtml(s) { // s is string
    var div = document.createElement('table');
    div.innerHTML = s;

    var tr = div.getElementsByTagName('tr');
    // ...
}

Heres a simple way to do it:

String.prototype.toDOM=function(){
  var d=document
     ,i
     ,a=d.createElement("div")
     ,b=d.createDocumentFragment();
  a.innerHTML=this;
  while(i=a.firstChild)b.appendChild(i);
  return b;
};

var foo="<img src='//placekitten.com/100/100'>foo<i>bar</i>".toDOM();
document.body.appendChild(foo);

Use insertAdjacentHTML(). It works with all current browsers, even with IE11.

_x000D_
_x000D_
var mylist = document.getElementById('mylist');_x000D_
mylist.insertAdjacentHTML('beforeend', '<li>third</li>');
_x000D_
<ul id="mylist">_x000D_
 <li>first</li>_x000D_
 <li>second</li>_x000D_
</ul>
_x000D_
_x000D_
_x000D_


For the heck of it I thought I'd share this over complicated but yet simple approach I came up with... Maybe someone will find something useful.

/*Creates a new element - By Jamin Szczesny*/
function _new(args){
    ele = document.createElement(args.node);
    delete args.node;
    for(x in args){ 
        if(typeof ele[x]==='string'){
            ele[x] = args[x];
        }else{
            ele.setAttribute(x, args[x]);
        }
    }
    return ele;
}

/*You would 'simply' use it like this*/

$('body')[0].appendChild(_new({
    node:'div',
    id:'my-div',
    style:'position:absolute; left:100px; top:100px;'+
          'width:100px; height:100px; border:2px solid red;'+
          'cursor:pointer; background-color:HoneyDew',
    innerHTML:'My newly created div element!',
    value:'for example only',
    onclick:"alert('yay')"
}));

Answer

  • Create a Template
  • Set the Template's innerHTML to your string .trim()
  • Create an Array of Template's children
  • Return children, child, or

_x000D_
_x000D_
function toElement(s='',c,t=document.createElement('template'),l='length'){
t.innerHTML=s.trim();c=[...t.content.childNodes];return c[l]>1?c:c[0]||'';}



console.log(toElement());
console.log(toElement(''));
console.log(toElement('    '));
console.log(toElement('<td>With td</td>'));
console.log(toElement('<tr><td>With t</td></tr>'));
console.log(toElement('<tr><td>foo</td></tr><tr><td>bar</td></tr>'));
console.log(toElement('<div><span>nested</span> <span>stuff</span></div>'));
_x000D_
_x000D_
_x000D_


For certain html fragments like <td>test</td>, div.innerHTML, DOMParser.parseFromString and range.createContextualFragment (without the right context) solutions mentioned in other answers here, won't create the <td> element.

jQuery.parseHTML() handles them properly (I extracted jQuery 2's parseHTML function into an independent function that can be used in non-jquery codebases).

If you are only supporting Edge 13+, it is simpler to just use the HTML5 template tag:

function parseHTML(html) {
    var t = document.createElement('template');
    t.innerHTML = html;
    return t.content.cloneNode(true);
}

var documentFragment = parseHTML('<td>Test</td>');

Here is working code for me

I wanted to convert 'Text' string to HTML element

var diva = UWA.createElement('div');
diva.innerHTML = '<a href="http://wwww.example.com">Text</a>';
var aelement = diva.firstChild;

Fastest solution to render DOM from string:

let render = (relEl, tpl, parse = true) => {
  if (!relEl) return;
  const range = document.createRange();
  range.selectNode(relEl);
  const child = range.createContextualFragment(tpl);
  return parse ? relEl.appendChild(child) : {relEl, el};
};

And here u can check performance for DOM manipulation React vs native JS

Now u can simply use:

let element = render(document.body, `
<div style="font-size:120%;line-height:140%">
  <p class="bold">New DOM</p>
</div>
`);

And of course in near future u use references from memory cause var "element" is your new created DOM in your document.

And remember "innerHTML=" is very slow :/


You can use the following function to convert the text "HTML" to the element

_x000D_
_x000D_
function htmlToElement(html)_x000D_
{_x000D_
  var element = document.createElement('div');_x000D_
  element.innerHTML = html;_x000D_
  return(element);_x000D_
}_x000D_
var html="<li>text and html</li>";_x000D_
var e=htmlToElement(html);
_x000D_
_x000D_
_x000D_


To enhance furthermore the useful .toDOM() snippet that we can find in different places, we can now safely use backticks (template literals).

So we can have single and double quotes in the foo html declaration.

This behave like heredocs for those familiar with the term.

This can be enhanced furthermore with variables, to make complex templating:

Template literals are enclosed by the back-tick () (grave accent) character instead of double or single quotes. Template literals can contain placeholders. These are indicated by the dollar sign and curly braces (${expression}). The expressions in the placeholders and the text between them get passed to a function. The default function just concatenates the parts into a single string. If there is an expression preceding the template literal (tag here), this is called a "tagged template". In that case, the tag expression (usually a function) gets called with the processed template literal, which you can then manipulate before outputting. To escape a back-tick in a template literal, put a backslash \ before the back-tick.

_x000D_
_x000D_
String.prototype.toDOM=function(){_x000D_
  var d=document,i_x000D_
     ,a=d.createElement("div")_x000D_
     ,b=d.createDocumentFragment()_x000D_
  a.innerHTML = this_x000D_
  while(i=a.firstChild)b.appendChild(i)_x000D_
  return b_x000D_
}_x000D_
_x000D_
// Using template litterals_x000D_
var a = 10, b = 5_x000D_
var foo=`_x000D_
<img _x000D_
  onclick="alert('The future start today!')"   _x000D_
  src='//placekitten.com/100/100'>_x000D_
foo${a + b}_x000D_
  <i>bar</i>_x000D_
    <hr>`.toDOM();_x000D_
document.body.appendChild(foo);
_x000D_
img {cursor: crosshair}
_x000D_
_x000D_
_x000D_

So, why not use directly .innerHTML +=? By doing so, the whole DOM is being recalculated by the browser, it's much slower.

https://caniuse.com/template-literals


var msg = "test" jQuery.parseHTML(msg)


HTML 5 introduced the <template> element which can be used for this purpose (as now described in the WhatWG spec and MDN docs).

A <template> element is used to declare fragments of HTML that can be utilized in scripts. The element is represented in the DOM as a HTMLTemplateElement which has a .content property of DocumentFragment type, to provide access to the template's contents. This means that you can convert an HTML string to DOM elements by setting the innerHTML of a <template> element, then reaching into the template's .content property.

Examples:

/**
 * @param {String} HTML representing a single element
 * @return {Element}
 */
function htmlToElement(html) {
    var template = document.createElement('template');
    html = html.trim(); // Never return a text node of whitespace as the result
    template.innerHTML = html;
    return template.content.firstChild;
}

var td = htmlToElement('<td>foo</td>'),
    div = htmlToElement('<div><span>nested</span> <span>stuff</span></div>');

/**
 * @param {String} HTML representing any number of sibling elements
 * @return {NodeList} 
 */
function htmlToElements(html) {
    var template = document.createElement('template');
    template.innerHTML = html;
    return template.content.childNodes;
}

var rows = htmlToElements('<tr><td>foo</td></tr><tr><td>bar</td></tr>');

Note that similar approaches that use a different container element such as a div don't quite work. HTML has restrictions on what element types are allowed to exist inside which other element types; for instance, you can't put a td as a direct child of a div. This causes these elements to vanish if you try to set the innerHTML of a div to contain them. Since <template>s have no such restrictions on their content, this shortcoming doesn't apply when using a template.

However, template is not supported in some old browsers. As of January 2018, Can I use... estimates 90% of users globally are using a browser that supports templates. In particular, no version of Internet Explorer supports them; Microsoft did not implement template support until the release of Edge.

If you're lucky enough to be writing code that's only targeted at users on modern browsers, go ahead and use them right now. Otherwise, you may have to wait a while for users to catch up.


function domify (str) {
  var el = document.createElement('div');
  el.innerHTML = str;

  var frag = document.createDocumentFragment();
  return frag.appendChild(el.removeChild(el.firstChild));
}

var str = "<div class='foo'>foo</div>";
domify(str);

You can create valid DOM nodes from a string using:

document.createRange().createContextualFragment()

The following example adds a button element in the page taking the markup from a string:

_x000D_
_x000D_
let html = '<button type="button">Click Me!</button>';_x000D_
let fragmentFromString = function (strHTML) {_x000D_
  return document.createRange().createContextualFragment(strHTML);_x000D_
}_x000D_
let fragment = fragmentFromString(html);_x000D_
document.body.appendChild(fragment);
_x000D_
_x000D_
_x000D_


Late but just as a note;

It's possible to add a trivial element to target element as a container and remove it after using.

// Tested on chrome 23.0, firefox 18.0, ie 7-8-9 and opera 12.11.

<div id="div"></div>

<script>
window.onload = function() {
    var foo, targetElement = document.getElementById('div')
    foo = document.createElement('foo')
    foo.innerHTML = '<a href="#" target="_self">Text of A 1.</a> '+
                    '<a href="#" onclick="return !!alert(this.innerHTML)">Text of <b>A 2</b>.</a> '+
                    '<hr size="1" />'
    // Append 'foo' element to target element
    targetElement.appendChild(foo)

    // Add event
    foo.firstChild.onclick = function() { return !!alert(this.target) }

    while (foo.firstChild) {
        // Also removes child nodes from 'foo'
        targetElement.insertBefore(foo.firstChild, foo)
    }
    // Remove 'foo' element from target element
    targetElement.removeChild(foo)
}
</script>

No need for any tweak, you got a native API:

const toNodes = html =>
    new DOMParser().parseFromString(html, 'text/html').body.childNodes[0]

You can use the following function to convert the text "HTML" to the element

_x000D_
_x000D_
function htmlToElement(html)_x000D_
{_x000D_
  var element = document.createElement('div');_x000D_
  element.innerHTML = html;_x000D_
  return(element);_x000D_
}_x000D_
var html="<li>text and html</li>";_x000D_
var e=htmlToElement(html);
_x000D_
_x000D_
_x000D_


Heres a simple way to do it:

String.prototype.toDOM=function(){
  var d=document
     ,i
     ,a=d.createElement("div")
     ,b=d.createDocumentFragment();
  a.innerHTML=this;
  while(i=a.firstChild)b.appendChild(i);
  return b;
};

var foo="<img src='//placekitten.com/100/100'>foo<i>bar</i>".toDOM();
document.body.appendChild(foo);

Here's my code, and it works:

function parseTableHtml(s) { // s is string
    var div = document.createElement('table');
    div.innerHTML = s;

    var tr = div.getElementsByTagName('tr');
    // ...
}