0

The following code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>A</title>
    <script type="text/javascript" src="./script.js" />
    <script type="text/javascript">alert("This is skipped.");</script>
</head>
<body>    
</body>
</html>

passes the validation test at W3C and Chrome does not display any Javascript errors on this page. However, the entire text <script type="text/javascript">alert("This is skipped."); is not parsed by the Javascript engine which just looks for the </script> tag even though it's self-closed. The file "script.js" is loaded, however.

In Chrome, Firefox and IE 11, this leads to this same behaviour.

Why is this? What is actually happening here?

Mike
  • 23,542
  • 14
  • 76
  • 87
Petr Hudeček
  • 1,623
  • 19
  • 30
  • 1
    The self closing tags are validated in html. And obviously that's not a javascript error which would stop execution that you suppose. – Bhojendra Rauniyar Sep 27 '14 at 15:09
  • 1
    This is valid _XML_, valid `application/xhtml+xml`, but _HTML_ actually derives from the older _SGML_, where there are a few concepts which are made mode generic (so equal) in _XML_, such as how a tag must be closed (self closed `br`, implicitly closed `p`, explicitly closed `textarea`); and `script` must be explicitly closed. – Paul S. Sep 27 '14 at 15:17

2 Answers2

5

The code you have is valid because you have an XHTML doctype. In XHTML any element is permitted to use the self-closing syntax (although it makes little sense for most of them).

If you were serving your document with an XML content type (Content-Type: application/xhtml+xml for example) then it would work in browsers too.

Since you are (presumably) serving the document with Content-Type: text/html, the browser will parse it as HTML.

  1. The first script tag will be parsed (the / will be ignored or treated as an invalid attribute).
  2. The second script tag will be parsed by the HTML parser as JavaScript (so it will be treated as text)
  3. The first script end tag will be parsed (and close the script tag from (1))
  4. Since the first script tag has a src attribute, the external script will be loaded and passed to the JS parser
  5. The inline "JavaScript" (the second script tag) won't be passed to the JS parser because a script element can't have an external and inline script (so you won't get a JS error from it). It may be added, as text, to the DOM though.

Note that the use of the self-closing syntax for script elements is banned by appendix C because HTML parsers do not give the desired result. All in all, XHTML is far more trouble then it is worth 99%+ of the time, and you should stick to using HTML instead of XHTML.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
0

The script element is generally used in two ways, to either contain code between the two tags of the script element or to include code. When it includes code it does not technically need the end tag for the script element.

The quickest way to test the code as actual XHTML (application/xhtml+xml) is to create a file with a .xhtml file extension and then open that file in Firefox. Gecko, unlike the two Webkit forks (Chrome and Safari) and Trident (IE) will actually break the page and instead show an XML parsing error message, other rendering engines will simply stop rendering at the point the XML parse error was encountered.

A few things about correctly handling script elements...

  1. There is no such mime as "text/javascript", it's actually application/javascript.
  2. Microsoft's IE doesn't understand JavaScript until IE9 and will simply not render JavaScript unless it's served with this non-existent weird mime "text/javascript". If you're building your own stuff 2014 or onwards simply ignore Internet Explorer 8 and older as their shares will be utterly negligible by the time you bring something to market.
  3. Avoid putting script elements in the body element if you're trying to learn how to code clean and strict, it'll force you to organize things; ensure you use the defer="defer" attribute/value pair if you had been putting script elements in the body for performance reasons.
  4. If you have a lot of scripts simply use a server scripting language like PHP to include() multiple files in a single file. You'll have to use Apache to enable PHP rendering in a *.js file and then you'll need to output the correct mime.

JavaScript Example

<script defer="defer" type="application/javascript">
//<![CDATA[
window.onload = function
{
 alert('Hello World.');
}
// ]]>
</script>

Everything that I've mentioned can be seen at my website in my profile as I code as strictly as possible. Sure strict code takes longer though I end up with almost utterly no maintenance which saves me hordes of time in the long run.

John
  • 1
  • 13
  • 98
  • 177