Chapter 2

JavaScript in HTML

WHAT’S IN THIS CHAPTER?

  • Using the <script> element
  • Comparing inline and external scripts
  • Examining how document modes affect JavaScript
  • Preparing for JavaScript-disabled experiences

The introduction of JavaScript into web pages immediately ran into the Web’s predominant language, HTML. As part of its original work on JavaScript, Netscape tried to figure out how to make JavaScript coexist in HTML pages without breaking those pages’ rendering in other browsers. Through trial, error, and controversy, several decisions were finally made and agreed upon to bring universal scripting support to the Web. Much of the work done in these early days of the Web has survived and become formalized in the HTML specification.

THE <SCRIPT> ELEMENT

The primary method of inserting JavaScript into an HTML page is via the <script> element. This element was created by Netscape and first implemented in Netscape Navigator 2. It was later added to the formal HTML specification. There are six attributes for the <script> element:

  • async — Optional. Indicates that the script should begin downloading immediately but should not prevent other actions on the page such as downloading resources or waiting for other scripts to load. Valid only for external script files.
  • charset — Optional. The character set of the code specified using the src attribute. This attribute is rarely used, because most browsers don’t honor its value.
  • defer — Optional. Indicates that the execution of the script can safely be deferred until after the document’s content has been completely parsed and displayed. Valid only for external scripts. Internet Explorer 7 and earlier also allow for inline scripts.
  • language — Deprecated. Originally indicated the scripting language being used by the code block (such as "JavaScript", "JavaScript1.2", or "VBScript"). Most browsers ignore this attribute; it should not be used.
  • src — Optional. Indicates an external file that contains code to be executed.
  • type — Optional. Replaces language; indicates the content type (also called MIME type) of the scripting language being used by the code block. Traditionally, this value has always been "text/javascript", though both "text/javascript" and "text/ecmascript" are deprecated. JavaScript files are typically served with the "application/x-javascript" MIME type even though setting this in the type attribute may cause the script to be ignored. Other values that work in non–Internet Explorer browsers are "application/javascript" and "application/ecmascript". The type attribute is still typically set to "text/javascript" by convention and for maximum browser compatibility. This attribute is safe to omit, as "text/javascript" is assumed when missing.

There are two ways to use the <script> element: embed JavaScript code directly into the page or include JavaScript from an external file.

To include inline JavaScript code, place JavaScript code inside the <script> element directly, as follows:

<script type="text/javascript">
    function sayHi(){
        alert("Hi!");
    }
</script>

The JavaScript code contained inside a <script> element is interpreted from top to bottom. In the case of this example, a function definition is interpreted and stored inside the interpreter environment. The rest of the page content is not loaded and/or displayed until after all of the code inside the <script> element has been evaluated.

When using inline JavaScript code, keep in mind that you cannot have the string "</script>" anywhere in your code. For example, the following code causes an error when loaded into a browser:

<script type="text/javascript">
    function sayScript(){
        alert("</script>");
    }
</script>

Because of the way that inline scripts are parsed, the browser sees the string "</script>" as if it were the closing </script> tag. This problem can be avoided easily by escaping the “/” character, as in this example:

<script type="text/javascript">
    function sayScript(){
        alert("</script>");
    }
</script>

The changes to this code make it acceptable to browsers and won’t cause any errors.

To include JavaScript from an external file, the src attribute is required. The value of src is a URL linked to a file containing JavaScript code, like this:

<script type="text/javascript" src="example.js"></script>

In this example, an external file named example.js is loaded into the page. The file itself need only contain the JavaScript code that would occur between the opening <script> and closing </script> tags. As with inline JavaScript code, processing of the page is halted while the external file is interpreted. (There is also some time taken to download the file.) In XHTML documents, you can omit the closing tag, as in this example:

<script type="text/javascript" src="example.js" />

This syntax should not be used in HTML documents, because it is invalid HTML and won’t be handled properly by some browsers, most notably Internet Explorer.

image

By convention, external JavaScript files have a .js extension. This is not a requirement, because browsers do not check the file extension of included JavaScript files. This leaves open the possibility of dynamically generating JavaScript code using JSP, PHP, or another server-side scripting language. Keep in mind, though, that servers often use the file extension to determine the correct MIME type to apply to the response. If you don’t use a .js extension, double-check that your server is returning the correct MIME type.

It’s important to note that a <script> element using the src attribute should not include additional JavaScript code between the <script> and </script> tags. If both are provided, the script file is downloaded and executed while the inline code is ignored.

One of the most powerful and most controversial parts of the <script> element is its ability to include JavaScript files from outside domains. Much like an <img> element, the <script> element’s src attribute may be set to a full URL that exists outside the domain on which the HTML page exists, as in this example:

<script type="text/javascript" src="http://www.somewhere.com/afile.js"></script>

Code from an external domain will be loaded and interpreted as if it were part of the page that is loading it. This capability allows you to serve up JavaScript from various domains if necessary. Be careful, however, if you are referencing JavaScript files located on a server that you don’t control. A malicious programmer could, at any time, replace the file. When including JavaScript files from a different domain, make sure you are the domain owner or the domain is owned by a trusted source.

Regardless of how the code is included, the <script> elements are interpreted in the order in which they appear in the page so long as the defer and async attributes are not present. The first <script> element’s code must be completely interpreted before the second <script> element begins interpretation, the second must be completed before the third, and so on.

Tag Placement

Traditionally, all <script> elements were placed within the <head> element on a page, such as in this example:

<!DOCTYPE html>
<html>
  <head>
    <title>Example HTML Page</title>
    <script type="text/javascript" src="example1.js"></script>
    <script type="text/javascript" src="example2.js"></script>
  </head>
  <body>
    <!-- content here -->
  </body>
</html>

The main purpose of this format was to keep external file references, both CSS files and JavaScript files, in the same area. However, including all JavaScript files in the <head> of a document means that all of the JavaScript code must be downloaded, parsed, and interpreted before the page begins rendering (rendering begins when the browser receives the opening <body> tag). For pages that require a lot of JavaScript code, this can cause a noticeable delay in page rendering, during which time the browser will be completely blank. For this reason, modern web applications typically include all JavaScript references in the <body> element, after the page content, as shown in this example:

<!DOCTYPE html>
<html>
  <head>
    <title>Example HTML Page</title>
  </head>
  <body>
    <!-- content here -->
    <script type="text/javascript" src="example1.js"></script>
    <script type="text/javascript" src="example2.js"></script>
  </body>
</html>

Using this approach, the page is completely rendered in the browser before the JavaScript code is processed. The resulting user experience is perceived as faster, because the amount of time spent on a blank browser window is reduced.

Deferred Scripts

HTML 4.01 defines an attribute named defer for the <script> element. The purpose of defer is to indicate that a script won’t be changing the structure of the page as it executes. As such, the script can be run safely after the entire page has been parsed. Setting the defer attribute on a <script> element signals to the browser that download should begin immediately but execution should be deferred:

<!DOCTYPE html>
<html>
  <head>
    <title>Example HTML Page</title>
    <script type="text/javascript" defer src="example1.js"></script>
    <script type="text/javascript" defer src="example2.js"></script>
  </head>
  <body>
    <!-- content here -->
  </body>
</html>

Even though the <script> elements in this example are included in the document <head>, they will not be executed until after the browser has received the closing </html> tag. The HTML5 specification indicates that scripts will be executed in the order in which they appear, so the first deferred script executes before the second deferred script, and both will execute before the DOMContentLoaded event (see Chapter 13 for more information). In reality, though, deferred scripts don’t always execute in order or before the DOMContentLoaded event, so it’s best to include just one when possible.

As mentioned previously, the defer attribute is supported only for external script files. This was a clarification made in HTML5, so browsers that support the HTML5 implementation will ignore defer when set on an inline script. Internet Explorer 4–7 all exhibit the old behavior, while Internet Explorer 8 and above support the HTML5 behavior.

Support for the defer attribute was added beginning with Internet Explorer 4, Firefox 3.5, Safari 5, and Chrome 7. All other browsers simply ignore this attribute and treat the script as it normally would. For this reason, it’s still best to put deferred scripts at the bottom of the page.

image

For XHTML documents, specify the defer attribute as defer="defer".

Asynchronous Scripts

HTML5 introduces the async attribute for <script> elements. The async attribute is similar to defer in that it changes the way the script is processed. Also similar to defer, async applies only to external scripts and signals the browser to begin downloading the file immediately. Unlike defer, scripts marked as async are not guaranteed to execute in the order in which they are specified. For example:

<!DOCTYPE html>
<html>
  <head>
    <title>Example HTML Page</title>
    <script type="text/javascript" async src="example1.js"></script>
    <script type="text/javascript" async src="example2.js"></script>
  </head>
  <body>
    <!-- content here -->
  </body>
</html>

In this code, the second script file might execute before the first, so it’s important that there are no dependencies between the two. The purpose of specifying an async script is to indicate that the page need not wait for the script to be downloaded and executed before continuing to load, and it also need not wait for another script to load and execute before it can do the same. Because of this, it’s recommended that asynchronous scripts not modify the DOM as they are loading.

Asynchronous scripts are guaranteed to execute before the page’s load event and may execute before or after DOMContentLoaded (see Chapter 13 for details). Firefox 3.6, Safari 5, and Chrome 7 support asynchronous scripts.

image

For XHTML documents, specify the async attribute as async="async".

Changes in XHTML

Extensible HyperText Markup Language, or XHTML, is a reformulation of HTML as an application of XML. The rules for writing code in XHTML are stricter than those for HTML, which affects the <script> element when using embedded JavaScript code. Although valid in HTML, the following code block is invalid in XHTML:

<script type="text/javascript">
    function compare(a, b) {
        if (a < b) {
            alert("A is less than B");
        } else if (a > b) {
            alert("A is greater than B");
        } else {
            alert("A is equal to B");
        } 
    }
</script>

In HTML, the <script> element has special rules governing how its contents should be parsed; in XHTML, these special rules don’t apply. This means that the less-than symbol (<) in the statement a < b is interpreted as the beginning of a tag, which causes a syntax error because a less-than symbol must not be followed by a space.

There are two options for fixing the XHTML syntax error. The first is to replace all occurrences of the less-than symbol (<) with its HTML entity (&lt;). The resulting code looks like this:

<script type="text/javascript">
    function compare(a, b) {
        if (a &lt; b) {
            alert("A is less than B");
        } else if (a > b) {
            alert("A is greater than B");
        } else {
            alert("A is equal to B");
        } 
    }
</script>

This code will now run in an XHTML page; however, the code is slightly less readable. Fortunately, there is another approach.

The second option for turning this code into a valid XHTML version is to wrap the JavaScript code in a CDATA section. In XHTML (and XML), CDATA sections are used to indicate areas of the document that contain free-form text not intended to be parsed. This enables you to use any character, including the less-than symbol, without incurring a syntax error. The format is as follows:

<script type="text/javascript"><![CDATA[
    function compare(a, b) {
        if (a < b) {
            alert("A is less than B");
        } else if (a > b) {
            alert("A is greater than B");
        } else {
            alert("A is equal to B");
        } 
    }
]]></script> 

In XHTML-compliant web browsers, this solves the problem. However, many browsers are still not XHTML-compliant and don’t support the CDATA section. To work around this, the CDATA markup must be offset by JavaScript comments:

<script type="text/javascript">
//<![CDATA[
    function compare(a, b) {
        if (a < b) {
            alert("A is less than B");
        } else if (a > b) {
            alert("A is greater than B");
        } else {
            alert("A is equal to B");
        } 
    }
//]]>
</script> 

This format works in all modern browsers. Though a little bit of a hack, it validates as XHTML and degrades gracefully for pre-XHTML browsers.

image

XHTML mode is triggered when a page specifies its MIME type as "application/xhtml+xml". Not all browsers officially support XHTML served in this manner.

Deprecated Syntax

When the <script> element was originally introduced, it marked a departure from traditional HTML parsing. Special rules needed to be applied within this element, and that caused problems for browsers that didn’t support JavaScript (the most notable being Mosaic). Nonsupporting browsers would output the contents of the <script> element onto the page, effectively ruining the page’s appearance.

Netscape worked with Mosaic to come up with a solution that would hide embedded JavaScript code from browsers that didn’t support it. The final solution was to enclose the script code in an HTML comment, like this:

<script><!--
    function sayHi(){
        alert("Hi!");
    }
//--></script>

Using this format, browsers like Mosaic would safely ignore the content inside of the <script> tag, and browsers that supported JavaScript had to look for this pattern to recognize that there was indeed JavaScript content to be parsed.

Although this format is still recognized and interpreted correctly by all web browsers, it is no longer necessary and should not be used. In XHTML mode, this also causes the script to be ignored because it is inside a valid XML comment.

INLINE CODE VERSUS EXTERNAL FILES

Although it’s possible to embed JavaScript in HTML files directly, it’s generally considered a best practice to include as much JavaScript as possible using external files. Keeping in mind that there are no hard and fast rules regarding this practice, the arguments for using external files are as follows:

  • Maintainability — JavaScript code that is sprinkled throughout various HTML pages turns code maintenance into a problem. It is much easier to have a directory for all JavaScript files so that developers can edit JavaScript code independent of the markup in which it’s used.
  • Caching — Browsers cache all externally linked JavaScript files according to specific settings, meaning that if two pages are using the same file, the file is downloaded only once. This ultimately means faster page-load times.
  • Future-proof — By including JavaScript using external files, there’s no need to use the XHTML or comment hacks mentioned previously. The syntax to include external files is the same for both HTML and XHTML.

DOCUMENT MODES

Internet Explorer 5.5 introduced the concept of document modes through the use of doctype switching. The first two document modes were quirks mode, which made Internet Explorer behave as if it were version 5 (with several nonstandard features), and standards mode, which made Internet Explorer behave in a more standards-compliant way. Though the primary difference between these two modes is related to the rendering of content with regard to CSS, there are also several side effects related to JavaScript. These side effects are discussed throughout the book.

Since Internet Explorer first introduced the concept of document modes, other browsers have followed suit. As this adoption happened, a third mode called almost standards mode arose. That mode has a lot of the features of standards mode but isn’t as strict. The main difference is in the treatment of spacing around images (most noticeable when images are used in tables).

Quirks mode is achieved in all browsers by omitting the doctype at the beginning of the document. This is considered poor practice, because quirks mode is very different across all browsers, and no level of true browser consistency can be achieved without hacks.

Standards mode is turned on when one of the following doctypes is used:

<!-- HTML 4.01 Strict -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
                   
<!-- XHTML 1.0 Strict -->
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 
<!-- HTML5 -->
<!DOCTYPE html>

Almost standards mode is triggered by transitional and frameset doctypes, as follows:

<!-- HTML 4.01 Transitional -->
<!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
                   
<!-- HTML 4.01 Frameset -->
<!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.01 Frameset//EN"
"http://www.w3.org/TR/html4/frameset.dtd">
                   
<!-- XHTML 1.0 Transitional -->
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   
<!-- XHTML 1.0 Frameset -->
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Frameset//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">

Because almost standards mode is so close to standards mode, the distinction is rarely made. People talking about “standards mode” may be talking about either, and detection for the document mode (discussed later in this book) also doesn’t make the distinction. Throughout this book, the term standards mode should be taken to mean any mode other than quirks.

THE <NOSCRIPT> ELEMENT

Of particular concern to early browsers was the graceful degradation of pages when the browser didn’t support JavaScript. To that end, the <noscript> element was created to provide alternate content for browsers without JavaScript. This element can contain any HTML elements, aside from <script>, that can be included in the document <body>. Any content contained in a <noscript> element will be displayed under only the following two circumstances:

  • The browser doesn’t support scripting.
  • The browser’s scripting support is turned off.

If either of these conditions is met, then the content inside the <noscript> element is rendered. In all other cases, the browser does not render the content of <noscript>.

Here is a simple example:

<!DOCTYPE html>
<html>
  <head>
    <title>Example HTML Page</title>
    <script type="text/javascript" defer="defer" src="example1.js"></script>
    <script type="text/javascript" defer="defer" src="example2.js"></script>
  </head>
  <body>
    <noscript>
      <p>This page requires a JavaScript-enabled browser.</p>
    </noscript>
  </body>
</html>

In this example, a message is displayed to the user when the scripting is not available. For scripting-enabled browsers, this message will never be seen even though it is still a part of the page.

SUMMARY

JavaScript is inserted into HTML pages by using the <script> element. This element can be used to embed JavaScript into an HTML page, leaving it inline with the rest of the markup, or to include JavaScript that exists in an external file. The following are key points:

  • To include external JavaScript files, the src attribute must be set to the URL of the file to include, which may be a file on the same server as the containing page or one that exists on a completely different domain.
  • All <script> elements are interpreted in the order in which they occur on the page. The code contained within a <script> element must be completely interpreted before code in the next <script> element can begin so long as defer and async attributes are not used.
  • For nondeferred scripts, the browser must complete interpretation of the code inside a <script> element before it can continue rendering the rest of the page. For this reason, <script> elements are usually included toward the end of the page, after the main content and just before the closing </body> tag.
  • You can defer a script’s execution until after the document has rendered by using the defer attribute. Deferred scripts always execute in the order in which they are specified.
  • You can indicate that a script need not wait for other scripts and also not block the document rendering by using the async attribute. Asynchronous scripts are not guaranteed to execute in the order in which they occur in the page.

By using the <noscript> element, you can specify that content is to be shown only if scripting support isn’t available on the browser. Any content contained in the <noscript> element will not be rendered if scripting is enabled on the browser.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.15.129.90