Приглашаем посетить
Андреев (andreev.lit-info.ru)

Authoring Scripts

Authoring Scripts

Scripts are not the only way to access the Dynamic HTML object model; the Dynamic HTML object model can be accessed in the following three ways:

All three methods manipulate Dynamic HTML in similar ways. This book concentrates on the first approach, accessing the object model through scripts that are associated with an HTML document. However, all the concepts and techniques presented in this book can also be applied to the other two methods.

The Script Element

Scripts behind the page can be associated with the document using one of three techniques. The most common technique is to enclose code within a Script element. (The other two techniques are to put the code in a separate file and reference it with a <SCRIPT> tag or to put the code in an event attribute in another tag.) The Script element is a container for code written in a specific programming language. A Script element can either contain the code in line inside the document or refer to an external file. Scripts contained within a Script element can be associated with an element through code, through special attributes on the Script element, or through language-dependent mechanisms. Individual elements can have scripts associated directly with them through event attributes exposed in the element itself.

The syntax for the Script element is as follows:

<SCRIPT LANGUAGE="languageName" [TYPE="
MIMEtype"]
          [SRC="optionalFile"] [DEFER]>
		       Script statements
			   </SCRIPT>

The scripting language is specified using the LANGUAGE attribute. The following code demonstrates how to specify a script for both VBScript and JavaScript:

<SCRIPT LANGUAGE="VBScript">
   ` VBScript code
</SCRIPT>

<SCRIPT LANGUAGE="JavaScript">
   // JavaScript code
</SCRIPT>


NOTE: In VBScript, comments are denoted by an apostrophe ('); in JavaScript, comments are denoted by either a // (which makes the rest of the line a comment) or /* contents */ (which makes contents a comment, even if it spans multiple lines). The scripting engine ignores all comment text.

For historical reasons, omitting a LANGUAGE attribute causes the script to be parsed as JavaScript. Rather than rely on the default language, you should always specify the LANGUAGE attribute in order to document the script's context.


NOTE: The Script element's LANGUAGE attribute is deprecated in HTML 4.0 in favor of using the TYPE attribute. The TYPE attribute takes a MIME type for the language: for JavaScript you use text/JavaScript, and for VBScript you use text/VBScript. However, because down-level browsers will not recognize the TYPE attribute, we recommend that you continue to use LANGUAGE or use both LANGUAGE and TYPE. Note that specifying a TYPE attribute, when recognized, overrides any LANGUAGE setting.

With the introduction of Netscape Navigator 3.0, Netscape started to append a version number to the JavaScript language string. Therefore, to write code that executes only in Netscape Navigator 3.0 and Microsoft Internet Explorer 4.0 and later, set the LANGUAGE attribute to JavaScript1.1. This technique works because if the browser does not recognize the specified language, the code is not executed and the script block is skipped. For code that demonstrates how to determine what scripting languages the client supports without having to check the browser version or type, see the section "Multiple Scripting Languages" later in this chapter.

Scripts contained within a Script element can execute code in two contexts: during the parsing of the page and as the result of an event. The following script demonstrates both types of code. Code that is included directly in the Script element but not contained within a function is executed immediately when it is parsed. Code that is contained within a function can execute only when the function is called, either directly or because of an event. Events are notifications that occur when the user interacts with the page or when the state of the document changes—for example, when the user clicks on the document, or when the document is loaded. The event model is introduced in detail in Chapter 3, "Dynamic HTML Event Model."

<HTML>
   <HEAD>
      <TITLE>Execution of Code</TITLE>
      <SCRIPT LANGUAGE="JavaScript">
         // The following alert occurs while the page is being loaded.
         alert(`Hello, World!');

         function helloWorld() {
            // This code executes only when the helloWorld function 
            // is called.
            alert(`Hello, World Too!');
         }
      </SCRIPT>
   </HEAD>
</HTML>

Script Libraries

Scripts may be contained in an external file and associated with any number of HTML documents. This arrangement serves several purposes, the most apparent of which is that it allows generic script libraries to be written that are shared by multiple pages. Depending on the browser, these script pages can become cached, thus increasing performance, as common functionality does not have to be written into every page. Another purpose depends on how pages are authored. If there are separate authors for scripts and contents, both do not need access to the same file simultaneously. Instead, the script author can write the scripts in one file, while the contents author writes the contents in another file. This is consistent with the separation of presentation and contents already available with style sheets.

Referencing of an external script is done using the SRC attribute, as in this example:

<SCRIPT LANGUAGE="JavaScript" SRC="genericFile.js">
   /* Optionally write code here for browsers that don't 
      support the SRC attribute. */
   // The closing SCRIPT tag is always required.
</SCRIPT>

Even when the SRC attribute is supplied, the <SCRIPT> tag must still have an end tag. Browsers that support the SRC attribute ignore the contents of the Script element. Browsers that do not recognize the SRC attribute execute the contents of the Script element as the code.

External script file support is available only in Netscape Navigator 3.0 and Internet Explorer 4.0 and later. Therefore, if you use external script files, take care to make provisions for the prior versions of these browsers.

Immediately Executed Code

As mentioned, Dynamic HTML lets you create code that can execute during the parsing of a page. This code is written outside the scope of any event handler, subroutine, or function. Such code can serve two main purposes:

The first purpose is similar to declaring what might normally be considered global variables. In all current scripting languages, variables that are scoped to the window object are added directly to the window object as properties. For example, here the variable x is added as a property to the window:

<SCRIPT LANGUAGE="JavaScript">
   var x = 0;           // Create property and initialize to 0.
   alert(window.x);  // Output 0, the value of x.
</SCRIPT>

To better understand the preceding code, consider the following, more elaborate example:

<SCRIPT LANGUAGE="JavaScript">
   // Create property x and initialize to 10.
   var x = 10;

   function foo() {
      // This code is not executed unless explicitly called.
      /* Create an instance variable, y, that lives only as 
         long as the function is being executed. */
      var y = 0;  
      alert(x);    // Output 10; x is a property of the window.
   }

   // Call foo while loading the page. 
   foo();
   window.foo();   // Call the foo function again because the foo
                   // function is added to the window.
</SCRIPT>

This code demonstrates that immediately executed code and functions can be interspersed. Code that calls a function while the page is loading must have the function declared in advance.

The second purpose of code that executes when the page loads is to write contents into the document. This is done using the document object's write method. Here is a simple program that writes Hello, World! into the HTML document:

<HTML>
   <HEAD>
      <TITLE>Hello, World!</TITLE> 
   </HEAD>
   <BODY>
      <SCRIPT LANGUAGE="JavaScript">
         // Write the string "Hello, World!" into the document.
         document.write("<H1>Hello, World!</H1>")
      </SCRIPT>
   </BODY>
</HTML>

The write method can be called only during the loading of the page, to insert contents into the parsing of the document. To manipulate and change the contents once the page is loaded, you must use a different technique. Dynamically adding contents to the document during the loading process is discussed in Chapter 6, "The HTML Document," and manipulating the contents is discussed in Chapter 13, "Dynamic Contents."

Locations of Scripts in the Document

A document may contain any number of Script elements. A Script element can live in either the head or the body of the document. For most purposes, the location of the script is not important in relation to the design of the page. However, scripts that perform initialization are usually more convenient and more readable when placed in the document's head.

The location of a Script element is more important if the element is actually writing contents into the stream or is referencing an element in the document. Writing into the stream is done using the write or writeln method of the document object, as in the following example:

<HTML>
   <SCRIPT LANGUAGE="JavaScript">
      // Generate an entire document from this script.
      document.write("<HEAD><TITLE>My Document</TITLE></HEAD>");
      document.write("<BODY><H1>This is my page.</H1></BODY>");
   </SCRIPT>
</HTML>

This code creates and renders the following HTML:

<HTML>
   <HEAD>
      <TITLE>My Document</TITLE>
   </HEAD>
   <BODY>
      <H1>This is my page.</H1>
   </BODY>
</HTML>

If you are writing head contents, it is important to put the script within the head. For example, a script placed in the middle of the page should not output HTML text that sets the document's title. Any time the write methods are called, the contents are placed into the stream at the current location. For example, inserting a <TITLE> tag in the wrong place may violate the HTML DTD (document type definition) and have unpredictable results.

The use of the write methods is discussed in detail in Chapter 6, "The HTML Document." Generating pages using document.write is not always an ideal technique because it masks the contents from editing and indexing tools, which might not be able to interpret scripts. Without executing the script behind the page, the actual contents are unknown.

Object Availability

Scripts that execute during the parsing of the page and that reference elements on the page need to be positioned carefully. For these scripts, only the elements that have been previously loaded are available for scripting because no forward declarations of elements are possible. The same holds true for any functions or variables that may be called—they must always be specified prior to the call.

Attempting to access anything in the HTML source code that follows the Script element during immediately executing code will generate an error. For example, scripts that execute in the head of the document while the page is downloading cannot reference any of the forms or other elements that exist in the body.

This rule is true only for scripts that execute during the downloading of a page. Scripts that execute in response to events are not required to follow the referenced element. Once the document is entirely parsed, all aspects of the document are considered fully accessible. However, it is possible for event handlers to be called before the document is entirely loaded. Before referencing an element that might not yet be loaded, you should test for the existence of the element:

<SCRIPT FOR="document" EVENT="onclick()" LANGUAGE="JavaScript">
   // This code executes whenever the user clicks in the document.

   // Verify that the element exists.
   if (null != document.all.myElement) {
      // Do something.
   }
   else
      alert("The document is not entirely loaded yet!");
</SCRIPT>

Event binding is discussed in Chapter 3, "Dynamic HTML Event Model."

Deferring Script Execution

Internet Explorer 4.0 can provide improved performance for scripts that do not contain immediately executed code. If the Script element contains only function declarations, supplying the DEFER attribute in the <SCRIPT> tag notifies the browser that it does not have to wait for the entire script to be parsed and interpreted. Instead, the browser can continue to load and display the page. This attribute should be used only when the Script element contains nothing but function declarations and when any subsequent scripts that are immediately executed do not call these functions. Immediately executed code defined within a deferred Script element can react unpredictably. When used appropriately, the DEFER attribute has no adverse effect on browsers that do not recognize it. Those browsers ignore the attribute and perform the traditional blocking until the script is parsed.

Multiple Scripting Languages

Similar to its ability to specify multiple Script elements, a single document can also contain and execute multiple scripting languages. All currently available scripting languages will execute on the page, assuming that the browser supports them. For example, using Internet Explorer, a page can be authored containing both JavaScript and VBScript code. Furthermore, it is possible for one language to call the functions defined by another language, as demonstrated in the following code. Calling a function scripted in another language is possible because all functions and variables are added as methods and properties of the window object.

<SCRIPT LANGUAGE="VBScript">
   ` Simple subroutine that pops up a message box
   sub MyAlert(str)
      msgBox(str)
   end sub
</SCRIPT>

<SCRIPT LANGUAGE="JavaScript">
   // Call the VBScript subroutine, MyAlert, defined above.
   MyAlert("Hello, World!");
   window.MyAlert("MyAlert is a method of the window object.");
</SCRIPT>

The fact that multiple languages can be used together makes possible an easy technique to determine what languages the browser supports. The following code demonstrates this technique:

<SCRIPT LANGUAGE="JavaScript1.1">
<!--
   window.js11 = true;  // Set flag for JavaScript 1.1.
// -->
</SCRIPT>

<SCRIPT LANGUAGE="VBScript">
<!--
   vbSupport = True     ` Set flag for VBScript.
` -->
</SCRIPT>

<SCRIPT LANGUAGE="JavaScript">
<!-- --><H1>Your browser does not support scripting.</H1>
<!--
   /* In this example, JavaScript is considered the lowest common
      denominator. This example can be modified to use a different
      language for the final testing. */
   document.write("JavaScript is supported.<BR>");
   if (null != window.js11)
      document.write("JavaScript 1.1 is supported.<BR>");
   if (null != window.vbSupport)
      document.write("VBScript is supported.<BR>");
// -->
</SCRIPT>

Hiding Scripts from Down-Level Browsers

Unless you take some precautions, browsers that do not support scripting will render the script code as part of the document's contents. This occurs because the down-level browser will ignore the <SCRIPT> tag and process the contents as HTML text. This is consistent with how HTML handles unrecognized tags and is necessary in the evolution of HTML. To hide scripts from a down-level browser, create an HTML comment that wraps the code:

<SCRIPT LANGUAGE="VBScript">
<!--
   ` VBScript code
   ` The next line ends the HTML comment.
` -->
</SCRIPT>

<SCRIPT LANGUAGE="JavaScript">
<!--
   // JavaScript code
// -->
</SCRIPT>

Both languages interpret the opening HTML string for creating a comment, <!--, as the beginning of a single-line comment, so the line is ignored by the language parser. The close comment must be preceded by the language-specific comment delineator (' in VBScript, // in JavaScript). This causes all code within the Script element to be treated as a comment and not rendered by a down-level browser.

When using the commenting scheme, be careful not to output the opening or closing comment delimiter in any strings anywhere in the code. If outputting the string is necessary, be sure to break it into multiple parts:

<SCRIPT LANGUAGE="JavaScript">
<!--
   /* The close comment tag being written into the document 
      is broken into two strings. */
   document.write("<" + "!-- This is a comment to write into the " +
      "stream. --" + ">");
// -->
</SCRIPT>

Using HTML comment tags inside a script hides the script from down-level browsers, but it does nothing to help warn the user that the page relies on scripting. Therefore, to supply text to a browser that does not support scripting, a special <NOSCRIPT> tag is exposed. The contents of a NoScript element are ignored by browsers that support scripting.

<!-- Contents for browsers without scripting support -->
<NOSCRIPT>
   <H1>This page requires scripting support.</H1>
   <H2>Please obtain the latest version of Internet Explorer 
      to properly view this page.</H2>
</NOSCRIPT>

This technique works in a down-level browser because the down-level browser ignores the <NOSCRIPT> tag just as it ignores the <SCRIPT> tag and outputs the contents. A scriptable browser knows that when it encounters a <NOSCRIPT> tag, it should not render anything until after the </NOSCRIPT> tag ends the element.

The user of a scriptable browser can disable scripting support. When scripting support is disabled, the browser acts like a down-level browser and outputs the NoScript element's contents.

Internet Explorer 4.0 allows you to disable scripts through its security settings. Internet Explorer 4.0 has a powerful security model that can be customized for different "zones" of Web content; each zone represents the entire Web, the intranet, or a particular set of pages. The following steps disable scripting for a particular zone:

  1. From the View menu, choose Internet Options to display an Internet Options dialog box.
  2. Select the Security tab from the list of pages.
  3. Select the zone to customize. Select Custom, and click the Settings button.
  4. In the Scripting category, select the Disable option for Active Scripting.
  5. Click OK or Apply to save these settings.

Netscape Navigator 2.0 does not support the <NOSCRIPT> tag. You must use another technique to warn the user that the page requires scripting. This involves writing a trivial script in the document that uses an enhancement of the commenting trick to force output on down-level clients:

<!-- Alternative technique for providing down-level contents -->
<SCRIPT LANGUAGE="JavaScript">
<!-- -->Your browser fails to recognize scripts. <!--
   // Write your code.
-->
</SCRIPT>

The commenting technique has the following disadvantage: when you disable scripts, the contents of the Script element are ignored, and the contents of the NoScript element are displayed. Therefore, the text for the comment is not displayed when scripting is disabled.

While the NoScript technique covers browsers that do not support scripting, it does nothing to differentiate vendor implementations. Different vendors will be implementing different versions of Dynamic HTML as it evolves. A script may or may not run on different browsers. There is unfortunately no easy solution to this problem. Some Web authors may choose to create multiple pages and send different pages based on the client's identity. This redirection can be done on the client. An example of this redirection is provided in the following section.


NOTE: In order to highlight the features of Dynamic HTML they demonstrate, most code samples in this book will not include any provisions for down-level browsers.

Client-Side Redirection

One method for handling different software versions is to redirect the user to different pages based on the client's browser, as shown in the following code. Client-side redirection occurs when a script behind the page conditionally switches the browser to a different document. By conditionally testing the version of the browser, an alternative version of the page can be loaded. When this technique is used, the base page should be the page that targets your most important audience because the redirection will have performance implications. When the redirection occurs, it will result in two pages being downloaded.

<SCRIPT LANGUAGE="JavaScript">
   var MS = navigator.appVersion.indexOf("MSIE");
   // Check whether this is IE4.
   window.isIE4 = (MS > 0) &&
      (parseInt(navigator.appVersion.substring(MS + 5, MS + 6)) >= 4);
   if (!isIE4) // If not IE4, get non-dynamic page.
      window.location="downlevelpage.htm";
</SCRIPT>

To avoid the performance implications of client-side redirection, you can perform the check on the server-side and send down only the correct page. However, depending on the server's privileges, this may not be a viable option.

[Содержание]