When should one use .innerHTML and when document.write in JavaScript - javascript

Is there a general rule, when one should use document.write to change the website content and when to use .innerHTML?
So far my rules were:
1) Use document.write when adding new content
2) Use .innerHTML when changing existing content
But I got confused, since someone told me that on the one hand .innerHTML is a strange Microsoft standard, but on the other hand I read that document.write is not allowed in XHTML.
Which structures should I use to manipulate my source code with JavaScript?

innerHTML can be used to change the contents of the DOM by string munging. So if you wanted to add a paragraph with some text at the end of a selected element you could so something like
document.getElementById( 'some-id' ).innerHTML += '<p>here is some text</p>'
Though I'd suggest using as much DOM manipulation specific API as possible (e.g. document.createElement, document.createDocumentFragment, <element>.appendChild, etc.). But that's just my preference.
The only time I've seen applicable use of document.write is in the HTML5 Boilerplate (look at how it checks if jQuery was loaded properly). Other than that, I would stay away from it.

innerHTML and document.write are not really comparable methods to dynamically change/insert content, since their usage is different and for different purposes.
document.write should be tied to specific use cases. When a page has been loaded and the DOM is ready you cannot use that method anymore. That's why is generally most used in conditional statements in which you can use it to syncronously load external javascript file (javascript libraries), including <script> blocks (e.g. when you load jQuery from the CDN in HTML5 Boilerplate).
What you read about this method and XHTML is true when the page is served along with the application/xhtml+xml mime type: From w3.org
document.write (like document.writeln) does not work in XHTML documents (you'll get a "Operation is not supported" (NS_ERROR_DOM_NOT_SUPPORTED_ERR) error on the error console). This is the case if opening a local file with a .xhtml file extension or for any document served with an application/xhtml+xml MIME type
Another difference between these approaches is related on insertion node: when you use .innerHTML method you can choose where to append the content, while using document.write the insertion node is always the part of document in which this method was used.

1) document.write() puts the contents directly to the browser where the user can see it.
this method writes HTML expressions or JavaScript code to a document.
The below example will just print ‘Hello World’ into the document
<html>
<body>
<script>
document.write("Hello World!");
</script>
</body>
</html>
2) document.innerHTML changes the inner content of an element
It changes the existing content of an element
The below code will change the content of p tag
<html>
<body>
<p id="test" onclick="myFun()">Click me to change my HTML content or my inner HTML</p>
<script>
function myFun() {
document.getElementById("test").innerHTML = "I'm replaced by exiesting element";
}
</script>
</body>
</html>
you could use document.write() without any connected HTML, but if you already have HTML that you want to change, then document.innerHTML would be the obvious choice.

I agree with the above comments. Basically:
document.write can be useful while the page is loading, to output new HTML tags or content while the browser is building the document object model. That content is output precisely where the JavaScript statement is embedded.
.innerHTML is useful at any time to insert new HTML tags/content as a string, and can be more easily directed to specific elements in the DOM regardless of when/where the JavaScript is run.
A couple of additional notes...
When document.write is called from a script outside of the body element, its output will be appended to the body element if called while the page is loading; but once the page is loaded, that same document.write will overwrite the entire document object model, effectively erasing your page. It all depends on the timing of document.write with the page load.
If you are using document.write to append new content to the end of the body element, you may be better off using this:
document.body.innerHTML += "A string of new content!";
It's a bit safer.

Related

Css not applying to Js 'document.write' [duplicate]

This:
function myFunction()
{
document.write("sup");
}
called in html like:
<div id="myDiv">
<script>myFunction();</script>
</div>t
adds a string sup to the myDiv div element. Which is what I want, exactly. However, this:
function loadFile(uri)
{
var r = new XMLHttpRequest();
document.write("trying to open: " + uri);
r.open('GET', uri, true);
r.send(null);
r.onreadystatechange = function()
{
if (r.readyState == 4)
{
myFunction();
}
}
}
function myFunction()
{
document.write("sup");
}
called like this:
<div id="myDiv">
<script>loadFile("filename.txt");</script>
</div>
seems to be overwriting my whole html file. I.e. when I run it in Firefox it shows me only the string sup (that's the whole content of the page) but the page seems to be still loading (the loading icon of FF is still there animating, apparently infinitely).
First of all, this is going to be used only locally, offline, as a fast and handy way of presenting data (using html+js and web browser instead of plain text file). What I want is to load a local text file and then put some of its content as a part of the html page. The same as in my first example but with loading the text file first.
The issue is that when you run document.write after the document has loaded, it overwrites the entire document. If it is run before that, it does not overwrite it.
What you want to do is set the innerHtml of a specific element, something like:
document.getElementById("myDiv").innerHTML="Sup";
Lets go over what a browser does when it receives an html file.
The window document is opened for writing. Imagine opening a text file.
Browser writes the contents to the document. A lot of magic happens in this step - objects get created and html rendered as boxes.
The window document closes the document. Kind of like saving the text file.
Now, modern browsers also expose a document API that allow you to do exactly those tasks using javascript.
You can open a document for writing using document.open(). You can also start writing content to the document using document.write(). Finally, you can close the document for writing using document.close(). Since the document always needs to be opened for writing before you write, calling document.write() always results in an implicit document.open().
Interspersing document.write() calls throughout an html body is a commonly used technique used to insert string contents dynamically into an html page.
For example, if you execute document.write("<p>holla</p>") in the body of an html file, the browser will do the following upon receiving the html file.
Open the document for writing.
Start writing the html contents to the document.
JavaScript engine will execute document.write() when it encounters it and then write "<p>holla</p>" into that specific line in the document, just as if the string was already part of the html file! Since document.write() is called during the parsing of an html file, it just gets parsed as part of the page.
Close the document for writing. Parsing complete.
If that's how you use document.write(), there would have been no surprise. Instead, you call document.write() after the html is parsed.
So what do you think should happen?
As I mentioned before, a document needs to be opened for writing before it is written to. In theory, we could either append to the existing content or just overwrite it. Well, if we append to the content, we'll end up with an invalid html page because the new values will appear after the closing tags. So the more sensible behavior is to overwrite the content and that's exactly what happens.

Removing from DOM content with function (which is attached to resize event) definition - results [duplicate]

As the title says, if I remove a script tag from the DOM using:
$('#scriptid').remove();
Does the javascript itself remain in memory or is it cleaned?
Or... am I completely misunderstanding the way in which browsers treat javascript? Which is quite possible.
For those interested in my reason for asking see below:
I am moving some common javascript interactions from static script files into dynamically generated ones in PHP. Which are loaded on demand when a user requires them.
The reason for doing this is in order to move the logic serverside and and run a small script, returned from the server, clientside. Rather than have a large script which contains a huge amount of logic, clientside.
This is a similar approach to what facebook does...
Facebook talks frontend javascript
If we take a simple dialog for instance. Rather than generating the html in javascript, appending it to the dom, then using jqueryUI's dialog widget to load it, I am now doing the following.
Ajax request is made to dialog.php
Server generates html and javascript that is specific to this dialog then encodes them as JSON
JSON is returned to client.
HTML is appended to the <body> then once this is rendered, the javascript is also appended into the DOM.
The javascript is executed automatically upon insertion and the dynamic dialog opens up.
Doing this has reduced the amount of javasript on my page dramatically however I am concerned about clean up of the inserted javascript.
Obviously once the dialog has been closed it is removed from the DOM using jQuery:
$('#dialog').remove();
The javascript is appended with an ID and I also remove this from the DOM via the same method.
However, as stated above, does using jQuery's .remove() actually clean out the javascript from memory or does it simple remove the <script> element from the DOM?
If so, is there any way to clean this up?
No. Once a script is loaded, the objects and functions it defines are kept in memory. Removing a script element does not remove the objects it defines. This is in contrast to CSS files, where removing the element does remove the styles it defines. That's because the new styles can easily be reflowed. Can you imagine how hard it would be to work out what a script tag created and how to remove it?
EDIT: However, if you have a file that defines myFunction, then you add another script that redefines myFunction to something else, the new value will be kept. You can remove the old script tag if you want to keep the DOM clean, but that's all removing it does.
EDIT2: The only real way to "clean up" functions that I can think of is to have a JS file that basically calls delete window.myFunction for every possible object and function your other script files may define. For obvious reasons, this is a really bad idea.
If your scripts have already executed removing the DOM elements are not going to get rid of them. Go to any page with JavaScript, open up your preferred javascript console and type $("script").remove(). Everything keeps running.
And this demonstrates #Kolink answer:
http://jsfiddle.net/X2mk8/2/
HTML:
<div id="output"></div>
<script id="yourDynamicGeneratedScript">
function test(n) {
$output = $("#output")
$output.append("test " + n + "<br/>")
}
test(1);
</script>
Javascript:
$("script").remove();
// or $("#yourDynamicGeneratedScript").remove();
test(2);
test(3);
test(4);
function test(n) {
$output = $("#output")
$output.append("REDEFINED! " + n + "<br/>")
}
test(5);
test(6);
test(7);

Non-invasive Javascript HTML injection

I'm looking for a non-invasive javascript HTML/CSS/JS injection into page.
I'm ideally looking to use document.write, but keep the original contents that were on the page. So doing the following:
javascript:document.write("blablabla"); - this removes all the content on page, I don't want to use innerHTML += to append the data.
Any suggestions?
If document.write is called after the onload event for the document it needs to re-open the document - effectively truncating it. While you can explicitly call document.write() inline (either with javascript directly embedded in the page or with a tag which does not use defer/async) this is considered bad practice as it blocks all the other processing of the page.
You can inject elements by constructing them in Javascript personally I prefer to set the innerHTML of an existing placeholder to an HTML fragment:
<div id='placeholder/></div>
...
document.getElementById('placeholder').innerHTML="<h2>hello world!</h2>";
(using createElement becomes messy and slow when creating/injecting complex HTML)
document.write will always overwrite the whole page as far I know. One option is to append/prepend your code to a div or to the bottom of your body.
$(elementObj).append(contents);
//or
$(elementObj).prepend(contents);
You can createElement() then use one of the methods above to inject your code into the newly created element.

Google Closure Ajax Content

How can I display the HTML content of a XHR responseText in a DIV and strip out its <script> tags and append them to the head tag? (using Google Closure)
Something like extractScripts in Prototype JS.
If the responseText is a whole web page with HTML and script tags, then maybe you should just attach it to an iFrame and the iFrame src and let the browser manage it all for you rather than put it in a DIV where you have to manage the different parts of the web page.
If you really want to get the responseText and put it directly into a div in your own document, then you have a couple options.
First, if the response is just an HTML fragment with embedded script tags (not a whole web page), then you can just read the whole response into a JS variable and then assign it to the .innerHTML attribute of your DIV. The browser will parse the HTML, including the embedded tags and evaluate it as if it was originally part of that div (except the script execution timing obviously isn't until right after you assign the .innerHTML.
As an example:
var myDiv = document.getElementById("myDiv");
myDiv.innerHTML = responseText;
Second, if there's some reason you want to pull out the tags separately (and I can't think of such a reason versus the first option), then you'll have to parse the start and end script tags out of the responseText yourself, put the JS code text in between them into a JS variable and use eval on that variable to execute it and make it part of your document. Then, assign the remaining HTML to the innerHTML attribute of your div as in the example above.
If that script has document.write in it, that won't work this second way because there's no location context for the document.write. If those script tags rely on any page loading methods like onload, then the scripts also won't see those events (except if it's the src of an iFrame.

Read IFrame content using JavaScript

Ok, This is my first time dealing seriously with IFrames and I cant seem to understand a few things:
First the sample code I am testing with:
<head>
<script type="text/javascript">
function init(){
console.log("IFrame content: " + window.frames['i1'].document.getElementsByTagName('body')[0].innerHTML);
}
</script>
</head>
<body onload="init();">
<iframe name="i1" src="foo.txt"/>
</body>
the file "foo.txt" looks like this:
sample text file
Questions:
1) The iframe seems to be behaving as a HTML document and the file text is actually part of the body instead. Why ? Is it a rule for an IFrame to be a HTML document. Is it not possible for the content of an iframe to be just plain text ??
2) The file content gets wrapped inside a pre tag for some reason. Why is this so ? Is it always the case?
3) My access method in the javascript is working but is there any other alternative? [native js solutions please] If the content is wrapped in a pre tag always then I will actually have to lookup inside the pre tag rather than lookup the innerHTML
I was having a hard time getting the contents of a TXT file that was the src of an iframe.
This is my solution:
document.getElementById( 'iframeID' ).contentWindow.document.body.innerText
innerHTML does not return the exact content of an element, its a non-standardized method that returns HTML which is equivalent to the real content, and in HTML the equivalent to plain text is <pre>foo...</pre>.
You might have better luck with the innerText property..
1) The iframe seems to be behaving as a HTML document and the file text is actually part of the body instead. Why ?
you’re using the DOM/JS interface. this will only work, if the content is treated as HTML/XML.
That's how browsers treat text files, because they 'look better' this way (not only inside iframe). Browsers can process lot's of file types, and it's unreasonable to expect them to show everything in raw form, right? Because browser pages (and iframes) are about presentation, nobody really uses iframes for configuration or to read raw data from the disk.
If you want to have full control over presentation, just change file type to html and it will be treated like html. (in particular, it will solve 'pre' problem)
Will this answer your questions?

Categories