Julien Genestoux
Julien Genestoux

Reputation: 32982

Create a DOM document from string, without JQuery

We're looking for ways to create a DOM document in javascript from a string, but without using Jquery. Is there a way to do so? [I would assume so, since Jquery can do it!]

For those curious, we can't use Jquery, becase we're doing this in the context of a Chrome application's content script, and using Jquery would just make our content script too heavy.

Upvotes: 34

Views: 37813

Answers (10)

Radim Šafrán
Radim Šafrán

Reputation: 598

Solution - works with all browsers since IE 4.0

var doc = (new DOMParser).parseFromString(htmlString, "text/html");

Or

var doc = document.implementation.createHTMLDocument();

1)Example: new DOMParser()

var htmlString = `<body><header class="text-1">Hello World</header><div id="table"><!--TABLE HERE--></div></body>`;
var insertTableString = `<table class="table"><thead><tr><th>th cell</th></tr></thead><tbody><tr><td>td cell</td></tr></tbody></table>`;
    
var doc = (new DOMParser).parseFromString(htmlString, "text/html");
    doc.getElementById('table').insertAdjacentHTML('beforeend', tableString);
    
console.log(doc);

2)Example: createHTMLDocument()

var htmlString = `<body><header class="text-1">Hello World</header><div id="table"><!--TABLE HERE--></div></body>`;
var insertTableString = `<table class="table"><thead><tr><th>th cell</th></tr></thead><tbody><tr><td>td cell</td></tr></tbody></table>`;

var doc = document.implementation.createHTMLDocument();
    doc.open();
    doc.write(htmlString);
    doc.getElementById('table').insertAdjacentHTML('beforeend', tableString);
    doc.close();

console.log(doc);

Upvotes: 3

Asfixia
Asfixia

Reputation: 1

The DOM element has the property innerHTML that allows to change completely its contents. So you can create a container and fill it with a new HTML content.

function createElementFromStr(htmlContent) {
  var wrapperElm = document.createElement("div");
  wrapperElm.innerHTML = htmlContent; // Ex: "<p id='example'>HTML string</p>"
  console.assert(wrapperElm.children.length == 1); //Only one child at first level.
  return wrapperElm.children[0];
}

* I know it is an old question, but i hope to help someone else.

Upvotes: 0

Zibri
Zibri

Reputation: 9827

fetch("index.html", {  // or any valid URL
    method: "get"
}).then(function(e) {
    return e.text().then(e => {
        var t = document.implementation.createHTMLDocument("");
        t.open();
        t.write(e);
        t.close();
        return t;
    });
}).then(e => {
    //  e will contain the document fetched and parsed.
    console.log(e);
});

Upvotes: 0

bobharley
bobharley

Reputation: 702

I was able to do this by writing the html string on an iframe

const html = `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>

</body>
</html>`

const iframe = document.createElement('iframe')
iframe.contentDocument.open()
iframe.contentDocument.write(html)
iframe.contentDocument.close()
iframe.addEventListener('load', () => {
  myDocumentObject = iframe.contentDocument
})

Upvotes: 0

Derek Ziemba
Derek Ziemba

Reputation: 2643

I tried some of the other ways here but there where issues when creating script elements such as Chrome refusing to load the actual .js file pointed to by the src attribute. Below is what works best for me.

It's up to 3x faster than jQuery and 3.5x faster than using DOMParser, but 2x slower than programmatically creating the element.
https://www.measurethat.net/Benchmarks/Show/2149/0

Object.defineProperty(HTMLElement, 'From', { 
    enumerable: false,
    value: (function (document) {
        //https://www.measurethat.net/Benchmarks/Show/2149/0/element-creation-speed
        var rgx = /(\S+)=(["'])(.*?)(?:\2)|(\w+)/g;
        return function CreateElementFromHTML(html) {
            html = html.trim();
            var bodystart = html.indexOf('>') + 1, bodyend = html.lastIndexOf('<');
            var elemStart = html.substr(0, bodystart);
            var innerHTML = html.substr(bodystart, bodyend - bodystart);
            rgx.lastIndex = 0;
            var elem = document.createElement(rgx.exec(elemStart)[4]);
            var match; while ((match = rgx.exec(elemStart))) {
                if (match[1] === undefined) {
                    elem.setAttribute(match[4], "");
                } else {
                    elem.setAttribute(match[1], match[3]);
                }
            }
            elem.innerHTML = innerHTML;
            return elem;
        };
    }(window.document))
});

Usage Examples:

HTMLElement.From(`<div id='elem with quotes' title='Here is "double quotes" in single quotes' data-alt="Here is 'single quotes' in double quotes"><span /></div>`);
HTMLElement.From(`<link id="reddit_css" type="text/css" rel="stylesheet" async href="https://localhost/.js/sites/reddit/zinject.reddit.css">`);
HTMLElement.From(`<script id="reddit_js" type="text/javascript" async defer src="https://localhost/.js/sites/reddit/zinject.reddit.js"></script>`);
HTMLElement.From(`<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">`);
HTMLElement.From(`<div id='Sidebar' class='sidebar' display=""><div class='sb-handle'></div><div class='sb-track'></div></div>`);

Upvotes: 0

apratimankur
apratimankur

Reputation: 803

https://developer.mozilla.org/en-US/docs/Web/API/DOMParser

var parser = new DOMParser();
var doc = parser.parseFromString("<html_string>", "text/html");

(the resulting doc variable is a documentFragment Object).

Upvotes: 61

woosteln
woosteln

Reputation: 232

In case you're still looking for an anwer, and for anyone else coming accross it, I just have been trying to do the same thing myself. It seems you want to be looking at javascript's DOMImplementation:

http://reference.sitepoint.com/javascript/DOMImplementation

There are few references to compatibility as well here, but it's fairly well supported.

In essence, to create a new document to manipulate, you want to create a new Doctype object (if you're going to output some standards based stuff) and then create the new Document using the newly created Doctype variable.

There are multiple options to be put into both the doctype and the document, but if you're creating an HTML5 document, it seems you want to leave most of them as blank strings.

Example (New HTML5 DOM Document):

var doctype = document.implementation.createDocumentType( 'html', '', '');

var dom = document.implementation.createDocument('', 'html', doctype);

The new Document now looks like this:

<!DOCTYPE html>
<html>
</html>

Example (New XHTML DOM Document):

var doctype = document.implementation.createDocumentType(
    'html',
    '-//W3C//DTD XHTML 1.0 Strict//EN',
    'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'
);

var dom = document.implementation.createDocument(
    'http://www.w3.org/1999/xhtml',
    'html',
    doctype
);

So it's up to you to populate the rest of it. You could do this as simply as changing

dom.documentElement.innerHTML = '<head></head><body></body>';

Or go with the more rigorous:

var head = dom.createElement( 'head' );
var body = dom.createElement( 'body' );
dom.documentElement.appendChild(head);
dom.documentElement.appendChild(body);

All yours.

Upvotes: 20

kirilloid
kirilloid

Reputation: 14304

createDocumentFragment may help you.

https://developer.mozilla.org/En/DOM/DocumentFragment

Browsers always create document by themselves with empty page (about:blank). Maybe, in Chrome application there're some functions available (like XUL in FF), but there's no such function in ordinary javascript.

Upvotes: 0

Srikanth Kshatriy
Srikanth Kshatriy

Reputation: 444

HTML would like this:

<html>
<head></head>
<body>
    <div id="toolbar_wrapper"></div>
</body>
</html>

JS would look like this:

var data = '<div class="toolbar">'+
                '<button type="button" class="new">New</button>'+
                '<button type="button" class="upload">Upload</button>'+
                '<button type="button" class="undo disabled">Undo</button>'+
                '<button type="button" class="redo disabled">Redo</button>'+
                '<button type="button" class="save disabled">Save</button>'+
            '</div>';
document.getElementById("toolbar_wrapper").innerHTML = data;

Upvotes: -1

Manatok
Manatok

Reputation: 5706

var dom = '<html><head>....</head><body>...</body></html>';

document.write(dom);
document.close();

Upvotes: -1

Related Questions