124

Instead of tediously search for workarounds for each type of attribute and event when using the following syntax:

elem = document.createElement("div");
elem.id = 'myID';
elem.innerHTML = ' my Text '
document.body.insertBefore(elem,document.body.childNodes[0]);

Is there a way where I can just declare the entire HTML element as a string? like:

elem = document.createElement("<div id='myID'> my Text </div>");
document.body.insertBefore(elem,document.body.childNodes[0]);

8 Answers 8

140

Instead of directly messing with innerHTML it might be better to create a fragment and then insert that:

function create(htmlStr) {
    var frag = document.createDocumentFragment(),
        temp = document.createElement('div');
    temp.innerHTML = htmlStr;
    while (temp.firstChild) {
        frag.appendChild(temp.firstChild);
    }
    return frag;
}

var fragment = create('<div>Hello!</div><p>...</p>');
// You can use native DOM methods to insert the fragment:
document.body.insertBefore(fragment, document.body.childNodes[0]);

Benefits:

  1. You can use native DOM methods for insertion such as insertBefore, appendChild etc.
  2. You have access to the actual DOM nodes before they're inserted; you can access the fragment's childNodes object.
  3. Using document fragments is very quick; faster than creating elements outside of the DOM and in certain situations faster than innerHTML.

Even though innerHTML is used within the function, it's all happening outside of the DOM so it's much faster than you'd think...

Sign up to request clarification or add additional context in comments.

7 Comments

I bet this createDocumentFragment() wouldn't be as good as the "legacy" innerHTML.
I really would like backward compatibility, so how could I use this alongside innerHTML, like I check if this method is not null, maybe?
This method works in all modern browsers. For IE 5.5 and below you could perform a check like:: if (document.createDocumentFragment) { create('...'); } else { /* Use innerHTML perhaps */ }
crescentfresh, I help on SO because I enjoy helping people; I'm sorry if a solution is not 100% operable in all situations. If you're so concerned why not offer your own solution instead of being unnecessarily critical of already-offered answers? With any abstraction there will always be edge-cases! This is a learning environment - we're not here to give people a solution on a plate - we're here to help each other become better at what we do! And sorry, but where did anyone mention "AJAX"?
Fair enough. My apologies. I just feel that there're so many abstractions on here with zero caveats mentioned.
|
102

You want this

document.body.insertAdjacentHTML( 'afterbegin', '<div id="myID">...</div>' );

6 Comments

@JonnyLeeds this doesn't seem to work on body element but works fine on any other element.
@Phill Of course it works on <body>. As a matter of fact, running it on <body> is my standard method of injecting stuff like style sheets into web pages via the console. What issue are you having?
@ŠimeVidas probably because the body element wasn't defined at execution time ... i paired your line with window.onload = function() { … } to prevent that problem
@Grandy Phill wrote that it works on other elements. If <body> were undefined, so would be all other elements, so this is likely not Phill’s issue.
@ŠimeVidas Hmm yeah you right ... if it works on anything it should work on body too
|
42

Have a look at insertAdjacentHTML

var element = document.getElementById("one");
var newElement = '<div id="two">two</div>'
element.insertAdjacentHTML( 'afterend', newElement )
// new DOM structure: <div id="one">one</div><div id="two">two</div>

position is the position relative to the element you are inserting adjacent to:

'beforebegin' Before the element itself

'afterbegin' Just inside the element, before its first child

'beforeend' Just inside the element, after its last child

'afterend' After the element itself

Comments

17

In old school JavaScript, you could do this:

document.body.innerHTML = '<p id="foo">Some HTML</p>' + document.body.innerHTML;

In response to your comment:

[...] I was interested in declaring the source of a new element's attributes and events, not the innerHTML of an element.

You need to inject the new HTML into the DOM, though; that's why innerHTML is used in the old school JavaScript example. The innerHTML of the BODY element is prepended with the new HTML. We're not really touching the existing HTML inside the BODY.

I'll rewrite the abovementioned example to clarify this:

var newElement = '<p id="foo">This is some dynamically added HTML. Yay!</p>';
var bodyElement = document.body;
bodyElement.innerHTML = newElement + bodyElement.innerHTML;
// note that += cannot be used here; this would result in 'NaN'

Using a JavaScript framework would make this code much less verbose and improve readability. For example, jQuery allows you to do the following:

$('body').prepend('<p id="foo">Some HTML</p>');

12 Comments

Pretty good. But I was interested in declaring the source of a new element's attributes and events, not the innerHTML of an element.
document.getElementsByTagName('body')[0] can indeed be replaced by document.body, good point. However, if you want to prepend or append the new HTML to another existing element instead of the BODY, you'll have to use document.getElementById() and/or document.getElementsByTagName(); that's why I used it in the example.
Also, your code can get very messy very quickly if you're directly adding/inserting "innerHTML"
@JimmyP: What rubbish! The very purpose of this question is to be able to directly insert HTML as strings instead of playing around with functions to construct it, attrib by attrib, node by node, element by element.
this detaches all event handlers and may cause memory leaks big time.
|
1

To my knowledge, which, to be fair, is fairly new and limited, the only potential issue with this technique is the fact that you are prevented from dynamically creating some table elements.

I use a form to templating by adding "template" elements to a hidden DIV and then using cloneNode(true) to create a clone and appending it as required. Bear in ind that you do need to ensure you re-assign id's as required to prevent duplication.

Comments

1

As others said the convenient jQuery prepend functionality can be emulated:

var html = '<div>Hello prepended</div>';
document.body.innerHTML = html + document.body.innerHTML;

While some say it is better not to "mess" with innerHTML, it is reliable in many use cases, if you know this:

If a <div>, <span>, or <noembed> node has a child text node that includes the characters (&), (<), or (>), innerHTML returns these characters as &amp, &lt and &gt respectively. Use Node.textContent to get a correct copy of these text nodes' contents.

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

Or:

var html = '<div>Hello prepended</div>';
document.body.insertAdjacentHTML('afterbegin', html)

insertAdjacentHTML is probably a good alternative: https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML

1 Comment

upvoted because you pointed me at textContent, the solution to copying the full HTMl from one node to another :)
0
document.body.insertAdjacentHTML(position, text)

This is worked for me, here is details about it: https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML

1 Comment

Please do not post duplicate answers, comment or vote up instead. This was used in 3 of the older answers.
-2

If you want to insert HTML code inside existing page's tag use Jnerator. This tool was created specially for this goal.

Instead of writing next code

    var htmlCode = '<ul class=\'menu-countries\'><li
        class=\'item\'><img src=\'au.png\'></img><span>Australia </span></li><li
        class=\'item\'><img src=\'br.png\'> </img><span>Brazil</span></li><li
        class=\'item\'> <img src=\'ca.png\'></img><span>Canada</span></li></ul>';
    var element = document.getElementById('myTag');
    element.innerHTML = htmlCode;

You can write more understandable structure

    var jtag = $j.ul({
        class: 'menu-countries',
        child: [
            $j.li({ class: 'item', child: [
                $j.img({ src: 'au.png' }),
                $j.span({ child: 'Australia' })
            ]}),
            $j.li({ class: 'item', child: [
                $j.img({ src: 'br.png' }),
                $j.span({ child: 'Brazil' })
            ]}),
            $j.li({ class: 'item', child: [
                $j.img({ src: 'ca.png' }),
                $j.span({ child: 'Canada' })
            ]})
        ]
    });
    var htmlCode = jtag.html();
    var element = document.getElementById('myTag');
    element.innerHTML = htmlCode;

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.