Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Comments on What problem does innerHTML solves?

Parent

What problem does innerHTML solves?

+2
−5

I understand that innerHTML does all the following actions:

  • It makes the element we work on (or even the entire DOM tree that we work on if that element is <body>) to be copy-pasted into a new empty document
  • The new document to which the data was copied, naturally lacks any JavaScript of the previous document
  • Although the data was copied into a new document, the browser will present the HTML change as if it was done in the original document

What problem would this property solve that can't be done with other methods, besides perhaps emptying the current document (why doing that?) and outputting the full HTML of an element (is it really the only way?)

About the MDN documentation:

  • Replacing the contents of an element: innerHTML does at least one extra thing as defuncting JavaScript so I would assume it's not a mere value replacement
  • Appending HTML to an element: I assume that this would typically be done with insertAdjacentHTML()?
History
Why does this post require moderator attention?
You might want to add some details to your flag.
Why should this post be closed?

3 comment threads

Can you provide an example of a change other than a replacement that supports your assumption? (5 comments)
`textContent` (like it's name implies) only does text (3 comments)
Documentation (2 comments)
Post
+7
−0

tl;dr

According to the documentation, innerHTML property "gets or sets the HTML or XML markup contained within the element". Basically, "that's all", but let's see it in more detail.


It makes the element we work on to be copy-pasted into a new empty document

No, the property itself doesn't copy anything (acessing element.innerHTML simply gets its value, but it doesn't make a copy of element). You can use its value and copy it to another element, though. And note that I said "element", not "document", because I can do this with any element in the DOM.

For example, let's suppose I have this HTML:

<div id="main">
  <p>lorem ipsum <span>dolor sit</span></p>
</div>
<div id="another"><p>some text</p></div>

And this JavaScript:

const main = document.querySelector('div#main');
const another = document.querySelector('div#another');

// copy main div's innerHTML to another div
another.innerHTML = main.innerHTML;

With this, the another div will have a copy of main div's contents: it'll have a p inside it (which in turn has a span). The old content (in this case, the paragraph with "some text") is replaced by the "lorem ipsum" paragraph (and also its children - in this case, the span "dolor sit" - as well). The result is both divs with the same contents.

Actually, when you set an element's innerHTML, the documentation says it does the following:

  1. The specified value is parsed as HTML or XML (based on the document type), resulting in a DocumentFragment object representing the new set of DOM nodes for the new elements.
  2. If the element whose contents are being replaced is a <template> element, then the <template> element's content attribute is replaced with the new DocumentFragment created in step 1.
  3. For all other elements, the element's contents are replaced with the nodes in the new DocumentFragment.

So, when I do element.innerHTML = someHTMLText, then someHTMLText is parsed and a DocumentFragment is created. This object is like a "lightweight document": it has nodes representing DOM elements, just like the document, but it contains only the nodes that were parsed. When the DocumentFragment is set to the element, it replaces whatever the element had before.

In the example above, when I do another.innerHTML = main.innerHTML, it first parses main.innerHTML (which is a string containing the HTML), resulting in a DocumentFragment, which is set to the another div (and any contents this div had before are replaced by the DocumentFragment). That's why the "some text" paragraph "disappears" and is replaced by the "lorem ipsum" one.

Therefore, using innerHTML is a way to copy contents from one element to another. But the property itself doesn't make copies. If I set element.innerHTML = someText and someText doesn't come from any existing element, it's not copying anything (just me being pedantic again).


Regarding "into a new empty document", I'm not sure what you mean. If you meant this:

document.body.innerHTML = someHTMLText;

Then you're not creating "a new empty document". You're just replacing the whole contents of the document's body by the new HTML text, which means the entire page will be replaced by that HTML. This doesn't create a new document, though.

Although the data was copied into a new document, the browser will present the HTML change as if it was done in the original document

As I said, it's not a new document. It's still the same, only its contents were changed.

The new document to which the data was copied, naturally lacks any whatsoever JavaScript of the previous document

Actually, the documentation says that script tags are also set to innerHTML, but they're not executed (although the same docs mention some ways to circumvent this).

emptying the current document (why doing that?)

I don't know, never needed to empty the current document.

But remind that innerHTML can be set to any element, not only the document.body. In this case, it's useful to make "dynamic things", such as elements changing according to some user actions (if I click somewhere, it updates some part of the page, etc).


outputting the full HTML of an element (is it really the only way?)

No, it's not the only way. But it's certainly the most straightforward one.

Other ways would be to do it manually, perhaps with this recursive function:

function getHtmlContent(el, str='') {
    if (el.nodeType === Node.TEXT_NODE) {
        str += el.textContent;
    } else {
        str += '<' + el.nodeName;
        if (el.attributes) {
            for (var i = 0; i < el.attributes.length; i++) {
                var attr = el.attributes[i];
                str += ' ' + attr.name + '="' + attr.value + '"';
            }
        }
        str += '>';
        for (var node of el.childNodes) {
            str = getHtmlContent(node, str);
        }
        str += '</' + el.nodeName + '>';
    }
    return str;
}

var html = getHtmlContent(someElement);

Which is tedious and error prone (I didn't test for very complex HTML structures, not sure how reliable it is).

Another option is to serialize the element, using a XMLSerializer:

var html = new XMLSerializer().serializeToString(el);

An important difference is that both solutions above include the elements tag, while innerHTML doesn't. Ex: if the element corresponds to <p><span>abc</span></p>, the paragraph's innerHTML is <span>abc</span>, while the solutions above also include the surrounding <p> tags. BTW, if you want the HTML to also include the own element's tag, just use outerHTML.


Replacing the contents of an element: innerHTML does some extra things so I would assume it's not a mere value replacement

Yes, it does extra things. As I previously said, setting element.innerHTML = someText makes someText to be fully parsed, creating a DocumentFragment, and replacing all the element's children by this new fragment. Which takes us to the next point:

Appending HTML to an element: I assume that this would typically be done with insertAdjacentHTML()?

I'd say insertAdjacentHTML is better than simply appending to innerHTML (although I still see a lot of code using the latter).

Appending to innerHTML like this:

element.innerHTML += someHTMLText;

Is considered bad because it forces a full parsing of the whole contents again. Remember that the code above is equivalent to:

element.innerHTML = element.innerHTML + someHTMLText;

Which means that I'm concatenating element.innerHTML and someHTMLText, and this creates a new string containing all the element's contents plus the new HTML text. Then this whole text will be parsed, resulting in a DocumentFragment, that will replace the element's contents.

insertAdjacentHTML would be a better solution to this case, because it parses only the new text being inserted. Hence, the code above could be changed to:

element.insertAdjacentHTML('beforeend', someHTMLText);

In this case, only someHTMLText is parsed, and inserted after the element's last child. This is better than parsing the whole element's contents (which is done when you append to innerHTML).


As a final note, setting innerHTML to the empty string is a way to remove all element's children. Also, directly setting innerHTML to some value is an option if you want to change the element's contents to something else entirely. But if you just want to change a small part of it (such as appending something in the end, or changing some specific child element), there are lots of other methods to do it (such as append, remove, replaceWith, etc).

History
Why does this post require moderator attention?
You might want to add some details to your flag.

2 comment threads

I as a non native English speaker, junior JavaScript programmer and as going through much stress, in ... (9 comments)
From your answer I could figure that `innerHTML` is a non-modular (does few different things that cou... (4 comments)
I as a non native English speaker, junior JavaScript programmer and as going through much stress, in ...
deleted user wrote over 2 years ago · edited over 2 years ago

I as a non native English speaker, junior JavaScript programmer and as going through much stress, in part due to massive down voting to my questions which I believe originates in personal persecution just can't understand your answer as a whole in this longevity and/or lack of ## headings; in my understanding, webwise it's just inaccessible, please consider to edit. I don't intend to go into any argument and plan to delete this comment soon enough, if you don't want to edit that's fine, I think I am pretty much done with this community.

hkotsubo‭ wrote over 2 years ago · edited over 2 years ago

deleted user You asked lots of things, including many misconceptions and misunderstandings about the language, and there was no way to address all of them with a short answer. Complaining that it's "too long", and saying that due to your junior level you can't understand advanced topics, are wrong reasons to downvote (specially when the answer is correct and actually answers the question).

If you're struggling to understand, I suggest you - without any irony - to give some steps back and study the language fundamental topics.

I stand by my answer. It's correct, complete (because it's meant to be useful not only for you, but for any future visitors), and downvoting for the reasons you pointed is simply wrong. I didn't downvote you, BTW...

hkotsubo‭ wrote over 2 years ago

Anyway, I'm also a non-native speaker of English, and don't know how to make the answer clearer... Perhaps we both must work on our English skills :-)

deleted user wrote over 2 years ago · edited over 2 years ago

hkotsubo‭ I don't think that my question symbols "misconceptions and misunderstandings about the language" because my question deals solely with the innerHTML property; you wrongly accuse me of misunderstanding "the language" due to some misunderstandings about innerHTML which does much more than mere HTML value replacing so to has a misleading name which is also easily confusable with innerText.

I have problems with texts I find (at a certain point in time) as long, dense, inaccessible, especially in English, in general, not just with the MDN literature (which tends to have such texts) or your answer.

You assumed that I down voted your answer, an assumption which is correct, but please next time say something like "if" you downvoted my answer because it may be a false assumption.

deleted user wrote over 2 years ago

hkotsubo‭ I have retracted the downvote due to what I recognize as sincerity, respect, and a real desire to understand me from your side.

deleted user wrote over 2 years ago · edited over 2 years ago

I want to add that in my elementary JavaScript studies in teamTreehouse.com none of the courses (at least as I remember) got down to such levels about innerHTML, I personally think that innerHTML is not an elementary topic in JavaScript.

hkotsubo‭ wrote over 2 years ago

deleted user If you have problems with long texts, I'm afraid there's nothing I can do to help. You asked lots of things, and in order to answer everything, it needs a reasonable amount of text (and I also admit I have difficulty to be succint, which makes things even "worse" for you). It seems we got to a dead end: I don't know how to make the answer even more clear and you ended up without a satisfactory answer. Sorry for not being able to help more...

hkotsubo‭ wrote over 2 years ago

deleted user And I apologize for sounding like an accusation, I really didn't mean that.

deleted user wrote over 2 years ago · edited over 2 years ago

hkotsubo‭ I think I have more of a problem with (what I grasp as) long passages rather than with long texts but again especially in English; it was always easy for me to read long passages in printed edition because then I could use markers of a given color order (Yellow, Orange, Green, Pink and Light-Blue) to split long passages into sub passages.

If Codidact would have had a team that splits dense question posts, i.e. question posts that contain more than one standalone question into several posts (I admit I have asked several things at once and it was a mistake) than I think that then all sides would have been more satisfied :)