Reputation: 3865
When I run this in Chrome (ver 2), it doesn't return the string, but it works in Firefox (ver 3). Why is this?
<html>
<head>
<script type="text/javascript">
function disp_prompt() {
var name=prompt("Please enter your name","Harry Potter");
if (name!=null && name!="") {
document.write("Hello " + name + "! How are you today?");
}
}
</script>
</head>
<body>
<input type="button" onclick="disp_prompt()" value="Display a prompt box" />
</body>
</html>
Upvotes: 9
Views: 17478
Reputation: 1439
Kind of late to the party, but I saw a violation in regards to document.write()
in Chrome DevTools with a link. Needless to say, it was an interesting read.
What's This About?
Starting in Chrome v55, Chrome is going to start blocking document.write()
under a very select set of circumstances. You can read about it here:
https://developers.google.com/web/updates/2016/08/removing-document-write
This should only come into effect for users who are on a 2G cellular connection, and possibly other types of connections which are slow. Here's an excerpt of the article in question:
With this data in mind, Chrome, starting with version 55, intervenes on behalf of all users when we detect this known-bad pattern by changing how document.write() is handled in Chrome (See Chrome Status). Specifically Chrome will not execute the elements injected via document.write() when all of the following conditions are met:
- The user is on a slow connection, specifically when the user is on 2G. (In the future, the change might be extended to other users on slow connections, such as slow 3G or slow WiFi.)
- The document.write() is in a top level document. The intervention does not apply to document.written scripts within iframes as they don't block the rendering of the main page.
- The script in the document.write() is parser-blocking. Scripts with the 'async' or 'defer' attributes will still execute.
- The script is not hosted on the same site. In other words, Chrome will not intervene for scripts with a matching eTLD+1 (e.g. a script hosted on js.example.org inserted on www.example.org).
- The script is not already in the browser HTTP cache. Scripts in the cache will not incur a network delay and will still execute.
- The request for the page is not a reload. Chrome will not intervene if the user triggered a reload and will execute the page as normal.
Third party snippets sometimes use document.write() to load scripts. Fortunately, most third parties provide asynchronous loading alternatives, which allow third party scripts to load without blocking the display of the rest of the content on the page.
So if your document.write()
meets all 6 criteria, then Chrome will block it. You should be able to see the message in DevTools when it happens.
The OP's Question
To address the OP's question, in order to use document.write()
you have to use document.open("text/html")
first. After you're done writing to the document, you need to use document.close()
. If you're just going to write plain text, then use document.open("text/plain")
. However, I recently read somewhere that Chrome ignores the mimetype and forces text/html.
<html>
<head>
<script type="text/javascript">
function disp_prompt() {
var name=prompt("Please enter your name","Harry Potter");
if (name!=null && name!="") {
document.open("text/plain");
document.write("Hello " + name + "! How are you today?");
document.close();
}
}
</script>
</head>
<body>
<input type="button" onclick="disp_prompt()" value="Display a prompt box" />
</body>
</html>
--OR--
You can modify the text that you write to include proper HTML like this:
document.write('<html><head></head><body>Hello ' + name + '! How are you today?</body></html>');
Don't forget to add document.open()
and document.close()
in all cases.
Upvotes: 0
Reputation: 536339
To append content to a document, you should only call document.write()
during the <script>-block parsing phase.
If you have a call to document.write
somewhere where it executes outside that context, such as in your event handler, there is no parsing going on, so nowhere for that string 'foo'
to go.
What should happen according to the original JavaScript reference is:
Event handlers execute after the original document closes, so the write method implicitly opens a new document of mimeType text/html if you do not explicitly issue a document.open method in the event handler.
That is, it assumes you've made a mistake and meant to do:
document.open('text/html');
document.write(html);
Which replaces the entire document with new content. You'll also notice that because you didn't finish that off by calling:
document.close();
...in Firefox, the ‘loading’ throbber is still animating, expecting more content to be written to the document (but it never comes).
In this case, you are document.write()
ing a string:
Hello bobince! How are you today?
that is clearly not a valid HTML document. Chrome (and Safari, which behaves the same) is trying to parse it as an HTML document, but fails because it is non-whitespace text content outside the document element (<html>), which is not allowed. If you put some tags in the name input:
Hello <em>bobince</em>! How are you today?
You'll see everything outside the <em> element is discarded. Firefox and IE manage to apply their “fix up text outside any element” broken-HTML-rule to save you, but Chrome doesn't.
If you want to document.write()
a new document, you should make sure it is indeed a complete document:
<html><head><title>Greetings</title><body><p>Hello bobince! How are you today?</p></body></html>
Or, if you want to document.write()
a text string, you should theoretically call:
document.open('text/plain');
before the write(). But beware, the mimetype parameter is not supported by Chrome or Safari; they'll always treat what you write as HTML.
In any case, you probably don't want to be using this method. If you want to add to (or change) the existing page you should normally be using DOM methods, such as setting the text on a status output div, or replacing the body contents using innerHTML.
document.write()
is needed in a few places (in particular, when you are creating a new window or frame from scratch), but otherwise it's generally the wrong thing and should be viewed with suspicion.
Upvotes: 32
Reputation:
Just add some paragraph tags in the write call:
<html>
<head>
<script type="text/javascript">
function disp_prompt() {
var name = window.prompt("Please enter your name", "Harry Potter");
if (name) {
window.document.write("<p>Hello " + name + "! How are you today?<\/p>");
}
}
</script>
</head>
<body>
<input type="button" onclick="disp_prompt()" value="Display a prompt box" />
</body>
</html>
Upvotes: 2
Reputation: 91432
don't use document.write. if you change it to soemthing like
if (name != null && name != "") {
document.getElementById('foo').innerHTML = "Hello " + name + "! How are you today?";
}
<body>
<input ...
<div id='foo'> </div>
</body>
document.write has pretty strange behavior. Where do you expect the text to be written to?
Upvotes: 9