12.2 Embedding JavaScript in HTML
Client-side JavaScript code is
embedded within HTML documents in a number of ways:
- Between a pair of <script> and
</script> tags - From an external file specified by the src
attribute of a <script> tag - In an event handler, specified as the value of an HTML attribute such
as onclick or onmouseover - As the body of
a URL that uses the
special javascript: protocol
The following sections document each of these JavaScript embedding
techniques in more detail. Together, they explain all the ways to
include JavaScript in web pages -- that is, they explain the
allowed structure of JavaScript programs on the client side.
12.2.1 The <script> Tag
Client-side
JavaScript scripts are part of an HTML file and are coded within
<script>
and </script> tags. You may place any number
of JavaScript statements between these tags; they are executed in
order of appearance, as part of the document loading process.
<script> tags may appear in either the
<head> or <body> of
an HTML document.
A single HTML document may contain
any number of nonoverlapping pairs of
<script> and
</script> tags. These multiple, separate
scripts are executed in the order in which they appear within the
document. While separate scripts within a single file are executed at
different times during the loading and parsing of the HTML file, they
constitute part of the same JavaScript program: functions and
variables defined in one script are available to all scripts that
follow in the same file. For example, you can have the following
script somewhere in an HTML page:
<script>var x = 1;</script>Later on in the same HTML page, you can refer to
x, even though it's in a different script
block. The context that matters is the HTML page, not the script
block:
<script>document.write(x);</script>The document.write( )
method is an important and commonly used one. When used as shown
here, it inserts its output into the document at the location of the
script. When the script finishes executing, the HTML parser resumes
parsing the document and starts by parsing any text produced with
document.write( ).
Example 12-1 shows a sample HTML file that includes a
simple JavaScript program. Note the difference between this example
and many of the code fragments shown earlier in this book: this one
is integrated with an HTML file and has a clear context in which it
runs. Note also the use of a language attribute in
the <script> tag. This is explained in the
next section.
Example 12-1. A simple JavaScript program in an HTML file
<html>
<head>
<title>Today's Date</title>
<script language="JavaScript">
// Define a function for later use
function print_todays_date( ) {
var d = new Date( ); // Get today's date and time
document.write(d.toLocaleString( )); // Insert it into the document
}
</script>
</head>
<body>
The date and time are:<br>
<script language="JavaScript">
// Now call the function we defined above
print_todays_date( );
</script>
</body>
</html>
12.2.1.1 The language and type attributes
Although JavaScript is by far the
most commonly used client-side scripting language, it is not the only
one. In order to tell a web browser what language a script is written
in, the <script> tag has
an optional language attribute. Browsers that
understand the specified scripting language run the script; browsers
that do not know the language ignore it.
If you are writing JavaScript code, use the
language attribute as follows:
<script language="JavaScript">
// JavaScript code goes here
</script>
If, for example, you are writing a script in
Microsoft's Visual Basic
Scripting Edition language,[2] you
would use the attribute like this:
[2] Also known as VBScript.
The only browser that supports VBScript is Internet Explorer, so
scripts written in this language are not portable. VBScript
interfaces with HTML objects in the same way that JavaScript does,
but the core language itself has a different syntax than JavaScript.
VBScript is not documented in this book. <script language="VBScript">
' VBScript code goes here (' is a comment character like // in JavaScript)
</script>
JavaScript is the default scripting language for the Web, and if you
omit the language attribute, both Netscape and
Internet Explorer will assume that your scripts are written in
JavaScript.
The HTML 4 specification standardizes the
<script> tag, but it deprecates the
language attribute because there is no standard
set of names for scripting languages. Instead, the specification
prefers the use of a type
attribute that specifies the scripting
language as a MIME type. Thus, in theory, the preferred way to embed
a JavaScript script is with a tag that looks like this:
<script type="text/javascript">In practice, the language attribute is still
better supported than this new type attribute.
The HTML 4 specification also defines a standard (and useful) way to
specify the default scripting language for an entire HTML
file. If you plan to use JavaScript as the only scripting language in
a file, simply include the following line in the
<head> of the document:
<meta http-equiv="Content-Script-Type" content="text/javascript">If you do this, you can safely use JavaScript scripts without
specifying the language or type
attributes.
Since JavaScript is the
default scripting language, those of us who program with it never
really need to use the language attribute to
specify the language in which a script is written. However, there is
an important secondary purpose for this attribute: it can also be
used to specify what version of JavaScript is required to interpret a
script. When you specify the language="JavaScript"
attribute for a script, any JavaScript-enabled browser will run the
script. Suppose, however, that you have written a script that uses
the exception-handling features of JavaScript 1.5. To avoid syntax
errors in browsers that do not support this version of the language,
you could embed your script with this tag:
<script language="JavaScript1.5">If you do this, only browsers that support JavaScript 1.5 (and its
exception-handling features) will run the script; any others will
ignore it.
The use of the
string
"JavaScript1.2" in the language
attribute deserves special mention. When Netscape 4 was being
prepared for release, it appeared that the emerging ECMA-262 standard
would require some incompatible changes to certain features of the
language. To prevent these incompatible changes from breaking
existing scripts, the designers of JavaScript at Netscape took the
sensible precaution of implementing the changes only when
"JavaScript1.2" was explicitly specified in the
language attribute. Unfortunately, the ECMA
standard was not finalized before Netscape 4 was released, and after
the release, the proposed incompatible changes to the language were
removed from the standard. Thus, specifying
language="JavaScript1.2" makes Netscape 4 behave
in ways that are not compatible with previous browsers or with the
ECMA specification. (See Section 11.6, for complete details on these
incompatibilities.) For this reason, you may want to avoid specifying
"JavaScript1.2" as a value for the
language attribute.
12.2.1.2 The </script> tag
You may at some point find yourself writing a script that uses the
document.write( ) method to output a script into
some other browser window or frame. If you do this, you'll need
to write out a </script> tag to terminate the
script you are writing. You must be careful, though -- the HTML
parser makes no attempt to understand your JavaScript code, and if it
sees the string "</script>" in your code, even if
it appears within quotes, it assumes that it has found the closing
tag of the currently running script. To avoid this problem, simply
break up the tag into pieces and write it out using an expression
like "</" + "script>":
<script>
f1.document.write("<script>");
f1.document.write("document.write('<h2>This is the quoted script</h2>')");
f1.document.write("</" + "script>");
</script>
Alternatively, you can escape the / in
</script> with a backslash:
f1.document.write("<\/script>");
12.2.1.3 The defer attribute
The HTML 4
standard defines an attribute of the
<script>
tag that is
not yet in common use but is nonetheless important. As I mentioned
briefly earlier, a script may call the document.write(
) method to dynamically add content to a document. Because
of this, when the HTML parser encounters a script, it must stop
parsing the document and wait for the script to execute.
If you write a script that does not produce any document
output -- for example, a script that defines a function but never
calls document.write( ) -- you may use the
defer attribute in the
<script> tag as a hint to the browser that
it is safe for it to continue parsing the HTML document and defer
execution of the script until it encounters a script that cannot be
deferred. Doing this may result in improved performance in browsers
that take advantage of the defer attribute. Note
that defer does not have a value; it simply must
be present in the tag:
<script defer>
// Any JavaScript code that does not call document.write( )
</script>
12.2.2 Including JavaScript Files
As of JavaScript 1.1, the
<script> tag supports a
src attribute. The value
of this attribute specifies the URL of a file containing JavaScript
code. It is used like this:
<script src="/image/library/english/10113_util.js"></script>A JavaScript file typically has a .js extension
and contains pure JavaScript, without
<script> tags or any other HTML.
A <script> tag with the
src attribute specified behaves exactly as if the
contents of the specified JavaScript file appeared directly between
the <script> and
</script> tags. Any code that does appear between
these tags is ignored by browsers that support the
src attribute (although it
is still executed
by browsers such as Netscape 2 that do not recognize the attribute).
Note that the closing </script> tag is
required even when the src attribute is specified
and there is no JavaScript between the
<script> and
</script> tags.
There are a number of advantages to using the src
tag:
- It simplifies your HTML files by allowing you to remove large blocks
of JavaScript code from them. - When you have a function or other JavaScript code used by several
different HTML files, you can keep it in a single file and read it
into each HTML file that needs it. This reduces disk usage and makes
code maintenance much easier. - When
JavaScript
functions are used by more than one page, placing
them in a separate JavaScript file allows them to be cached by the
browser, making them load more quickly. When JavaScript code is
shared by multiple pages, the time savings of caching more than
outweigh the small delay required for the browser to open a separate
network connection to download the JavaScript file the first time it
is requested. - Because the src attribute takes an arbitrary URL
as its value, a JavaScript program or web page from one web server
can employ code (such as subroutine libraries) exported by other web
servers.
12.2.3 Event Handlers
JavaScript
code in a
script is executed once, when the HTML file that contains it is read
into the web browser. A program that uses only this sort of static
script cannot dynamically respond to the user. More dynamic programs
define event handlers that are automatically invoked by the web
browser when certain events occur -- for example, when the user
clicks on a button within a form. Because events in client-side
JavaScript originate from HTML objects (such as buttons), event
handlers are defined as attributes of those objects. For example, to
define an event handler that is invoked when the user clicks on a
checkbox in a form, you specify the handler code as an attribute of
the HTML tag that defines the checkbox:
<input type="checkbox" name="opts" value="ignore-case"
onclick="ignore-case = this.checked;">
What's
of interest to us here is the onclick
attribute.[3] The string value of
the onclick attribute may contain one or more
JavaScript statements. If there is more than one
statement, the statements must be separated from each other with
semicolons. When the specified event -- in this case, a
click -- occurs on the checkbox, the JavaScript code within the
string is executed.
[3] All HTML event handler attribute names
begin with "on".While you can include any number of JavaScript statements within an
event handler definition, a common technique when more than one or
two simple statements are required is to define the body of an event
handler as a function between <script> and
</script> tags. Then you can simply invoke
this function from the event handler. This keeps most of your actual
JavaScript code within scripts and reduces the need to mingle
JavaScript and HTML.
We'll cover events and event handlers in much more detail in
Chapter 19, but you'll see them used in a
variety of examples before then. Chapter 19
includes a comprehensive list of event handlers, but these are the
most common:
onclick
This handler is supported by all button-like form elements, as well
as <a> and <area>
tags. It is triggered when the user clicks on the element. If an
onclick handler returns false,
the browser does not perform any default action associated with the
button or link; for example, it doesn't follow a hyperlink (for
an <a> tag) or submit a form (for a
Submit button).
onmousedown
, onmouseup
These two event handlers are a lot like onclick,
but they are triggered separately when the user presses and releases
a mouse button. Document elements that support
onclick also support these handlers. In IE 4 and
Netscape 6, these handlers are actually supported by just about all
document elements.
onmouseover
, onmouseout
These two event handlers are triggered when the mouse pointer moves
over or out of a document element, respectively. They are used most
frequently with <a> tags. If the
onmouseover handler of an
<a> tag returns true, it
prevents the browser from displaying the URL of the link in the
status line.
onchange
This event handler is supported by the
<input>
,
<select>, and
<textarea> elements. It is triggered when
the user changes the value displayed by the element and then tabs or
otherwise moves focus out of the element.
onsubmit
, onreset
These event handlers are supported by the
<form> tag and are triggered when the form
is about to be submitted or reset. They can return
false to cancel the submission or reset. The
onsubmit handler is commonly used to perform
client-side form validation.
For a realistic example of the use of event handlers, take another
look at the interactive loan-payment script in Example 1-3. The HTML form in this example contains a
number of event handler attributes. The body of these handlers is
simple: they simply call the calculate( ) function
defined elsewhere within a <script>.
12.2.4 JavaScript in URLs
Another way
that JavaScript
code can be included on the client side
is in a URL following the
javascript: pseudoprotocol
specifier. This special protocol type specifies that the body of the
URL is arbitrary JavaScript code to be run by the JavaScript
interpreter. If the JavaScript code in a
javascript: URL contains multiple statements, the
statements must be separated from one another by semicolons. Such a
URL might look like this:
javascript:var now = new Date( ); "<h1>The time is:</h1>" + now;When the browser loads one of these JavaScript URLs, it executes the
JavaScript code contained in the URL and uses the string value of the
last JavaScript statement as the contents of the new document to
display. This string value may contain HTML tags and is formatted and
displayed just like any other document loaded into the browser.
JavaScript URLs may also contain JavaScript
statements that
perform actions but return no value. For example:
javascript:alert("Hello World!")When this sort of URL is loaded, the browser executes the JavaScript
code, but because there is no value to display as the new document,
it does not modify the currently displayed document.
Often, we want to use a javascript: URL to execute
some JavaScript code without altering the currently displayed
document. To do this, you must be sure that the last statement in the
URL has no return value. One way to ensure this is to use the
void operator to explicitly specify an undefined return
value. Simply use the statement void 0; at the end
of your javascript: URL. For example, here is a
URL that opens a new, blank browser window without altering the
contents of the current window:
javascript:window.open("about:blank"); void 0;
Without the void operator in this URL, the return
value of the Window.open(
) method call would be converted to a
string and displayed, and the current document would be overwritten
by a document that appears something like this:
[object Window]You can use a javascript: URL anywhere you'd
use a regular URL. One important way to use this syntax is to type it
directly into the Location field of
your browser, where you can test arbitrary JavaScript code without
having to open your editor and create an HTML file containing the
code.
javascript: URLs can be used in bookmarks, where
they form useful mini-JavaScript programs, or
"bookmarklets," that can be easily launched from a menu
or toolbar of bookmarks.
javascript: URLs can also be used as the
href value of a hyperlink. When the user clicks on
such a link, the specified JavaScript code is executed. Or, if you
specify a javascript:
URL as the value of the
action attribute of a
<form> tag, the JavaScript code in the URL
is executed when the user submits the form. In these contexts, the
javascript: URL is essentially a substitute for an
event handler.
There are a few circumstances where a javascript:
URL can be used with objects that do not support event handlers. For
example, the <area> tag does not support an
onclick event handler on Windows platforms in
Netscape 3 (though it does in
Netscape 4). So, if you want to execute JavaScript code when the user
clicks on a client-side image map in Netscape 3, you must use a
javascript: URL.
12.2.5 JavaScript in Nonstandard Contexts
Both Netscape and Microsoft have implemented proprietary extensions
in their browsers, and you may occasionally see JavaScript code in a
context other than those described here. For example,
Internet Explorer allows you to
define event handlers in a <script> tag that
uses special for and event
attributes. Netscape
4 allows you to use JavaScript as an alternative syntax for defining
CSS style sheets within a <style> tag.
Netscape 4 also extends the HTML entity syntax and allows JavaScript
to appear within entities (but only within the values of HTML
attributes). This can result in HTML that looks like this:
<table border="&{getBorderWidth( )};">Finally, Netscape 4 also supports a form of conditional comment based
on this JavaScript entity syntax. Note that Netscape 6 and the
Mozilla browser on which it is based no longer support these
nonstandard uses of JavaScript.