cover
Copyright© 1999 by Eric M. Schurman and William J. Pardi


LOC Page

PUBLISHED BY
Microsoft Press
A Division of Microsoft Corporation
One Microsoft Way
Redmond, Washington 98052-6399

Copyright © 1999 by Eric M. Schurman and William J. Pardi.

All rights reserved. No part of the contents of this book may be reproduced or transmitted in any form or by any means without the written permission of the publisher.

Library of Congress Cataloging-in-Publication Data

Schurman, Eric. M.

        Dynamic HTML in Action / Eric M. Schurman, William J. Pardi. --

    2nd ed.

            p.      cm.

        Pardi appears first on previous ed.

        Includes index.

        ISBN 0-7356-0563-7

        1. DHTML (Document markup language)    I. Pardi, William J.

    II.  Title.

    QA76.76.H94P37  1999

    005.7'2--dc21                                                                   98-51581

                                                                                CIP

Printed and bound in the United States of America.

1 2 3 4 5 6 7 8 9 MLML 4 3 2 1 0 9

Distributed in Canada by ITP Nelson, a division of Thomson Canada Limited.

A CIP catalogue record for this book is available from the British Library.

Microsoft Press books are available through booksellers and distributors worldwide. For further information about international editions, contact your local Microsoft Corporation office or contact Microsoft Press International directly at fax (425) 936-7329. Visit our Web site at mspress.microsoft.com.

Macintosh is a registered trademark of Apple Computer, Inc. used under license. Active Channel, ActiveX, Chromeffects, DirectAnimation, DirectX, JScript, Microsoft, the Microsoft Internet Explorer logo, MSDN, NetShow, PowerPoint, Visual Basic, Visual C++, Visual Interdev, Visual J++, Visual Studio, Windows, and Windows NT are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries. Other product and company names mentioned herein may be the trademarks of their respective owners.

The example companies, organizations, products, people, and events depicted herein are fictious. No association with any real company, organization, product, person, or event is intended or should be inferred.

Acquisitions Editor: Juliana Aldous

Project Editor: Thom Votteler

Technical Editor: Tim Upton and Linda Harmony


Acknowledgments

Foremost, thanks go to Microsoft Press. Without the massive efforts of its editors, technical editors, proofreader/copy editors, indexers, artists, and compositors, this book would never have come to fruition. Professionals like these let us focus on writing while they take care of the innumerable details that are required to get a finished product out the door. Additional thanks go the acquisitions editors for trusting in our vision and to the sales and marketing staff for actually getting this book into your hands.

We also would like to thank our families and friends: Cari, Murphy, Bayley, Sebastian, Jodie, Cody, Ryan, and everyone else who showed great patience during the long nights and weekends of writing and editing. We couldn’t have done it without your support.


What Is Dynamic HTML?

Introduction

This is the second edition of Dynamic HTML in Action. We conceived the idea for the first edition of this book when we were developing computer applications with early beta versions of Microsoft Internet Explorer 4. At the time, we knew of no resource that demonstrated how the various emerging technologies for the World Wide Web could be used together. The first edition became the resource we wanted. Since that time, we have developed numerous sites for the Web and worked with a variety of browsers, including many versions of both Netscape Navigator and Internet Explorer. Dynamic HTML in Action, Second Edition reflects what we’ve learned.

Developing for the Web requires an understanding of how various browsers behave, as well as knowledge of a range of technologies, including Hypertext Markup Language (HTML), script, Cascading Style Sheets (CSS), multimedia, and more. Our intent in this book is to help you to create cross browser content for the Web quickly and effectively.

What You Should Know

This book is aimed at those who have at least basic computer knowledge and some familiarity with the World Wide Web and Web browsers. You might be interested in this book if you are

  • A novice who is familiar with the Web and eager to begin creating simple HTML documents

  • A Web developer looking to expand your knowledge of scripting and DHTML

  • An experienced programmer who wants to move into Internet technologies

You do not need programming experience to learn from this book, although it would probably make the scripting topics a bit easier to understand. Knowledge of HTML is helpful, although we will cover some HTML basics in the early chapters.

This book includes numerous code samples, both in the text and on the companion CD-ROM. You can use these samples as models for your own projects or as a source of ideas if you are stuck on a particular problem. You can even copy the samples and use them in your own pages.

Web Links

Most of the following chapters contain Web addresses pointing to various references. Although these were accurate and active at the time this book was written, please remember that sites on the Web change often; some of the addresses cited in the book might no longer be active when you try to access them. To minimize this problem, we have created a Web page that will be updated to contain active versions of many of these online links. This page is available as the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm, or by opening the file named MSDN_OL.htm on the companion CD.

Throughout this book, we refer to information available on the Microsoft Site Builder Network (SBN). Most of these resources can be accessed on the companion CD or on the Internet. To access a topic on the CD, open the file Workshop (References).htm, and then navigate as described to that particular topic. These topics are also available on the Internet. To get to the online versions, visit the MSDN Online Resource page described above, or go to microsoft.com/sitebuilder.

Organization of This Book

This book is organized into parts. We begin with the most basic concepts and technologies that represent the core of Web development. As the book progresses, it builds upon this base to cover techniques that give you more sophisticated control over the browser. Toward the end of the book are a number of technologies that are specific to a particular browser, or that are of a fairly technical nature.

Part I
HTML: The Framework for Active Web Content

The chapters in Part I provide an overview of some of what is possible with Dynamic HTML; they also introduce HTML, the underlying standard that governs how Web pages are displayed in browsers. In this part, we cover everything from formatting text to creating tables and complex forms. The final chapter in this Part introduces the concept of an Object Model, which allows manipulation of a page’s content through script.

Part II
Adding Interactivity: Using Scripts To Activate Your Page

In Part II, we discuss scripting, which can be used to perform programmatic tasks within the browser. In this book, we focus on JScript and JavaScript (respectively, the Microsoft and Netscape implementations of the same scripting standard) because of their widespread support. The chapters in this Part cover topics ranging from data types and functions to conditionals, error handling, and manipulation of the Object Model.

Part III
Text and Page Layout: Using Cascading Style Sheets

Part III covers the use of Cascading Style Sheets (CSS), a standard that enables you to separate content from formatting and simultaneously gain a high level of control over the appearance of your Web pages. This Part also discusses the manipulation of CSS with script, as well as the use of Visual Filters and Transitions.

Part IV
Multimedia

Part IV teaches you how to manage multimedia on your page. Topics discussed range from video and audio to the DirectAnimation multimedia controls, which offer such useful features as the exact timing of events and movement, and vector graphics. Part IV also discusses the challenges of successfully implementing multimedia on the Web.

Part V
Advanced Techniques: Data Binding, XML, and More

The chapters in Part V cover a wide variety of topics, ranging from DHTML Behaviors and cookies to the integration of data into Web pages. An entire chapter in this Part is devoted to the challenges of creating cross browser Web content. The final chapter rolls together a large number of the techniques discussed in this book into a sample Web site.

Appendixes

The four appendixes discuss troubleshooting, list a number of useful tools and resources, provide Object Model documentation, and offer a substantial reference of character entities.

What’s on the Companion CD?

At the back of the book, you’ll find a companion CD, which contains:

  • A Readme.txt file that explains how to install and use the various components on the CD

  • All the code samples in the book, organized by chapter number

  • A sample Web site, accessible by running the SampSite.htm file

  • An electronic version of the book in HTML format, in the Ebook folder

  • A snapshot of the SBN Workshop Web site, containing many references and samples

  • Full documentation for JScript and VBScript, in the Tools folder

  • Various tools in the Tools folder


Chapter 1 -- An Overview of Dynamic HTML

 Chapter 1

An Overview of Dynamic HTML

If you have followed the growth of the World Wide Web (WWW or Web) over the past few years, you might have heard the term "Internet time." The incredible growth of the Internet and the Web has spawned dozens of new enterprises that have produced thousands of new applications (or "apps," as they're known in the industry). In the race to beat competitors to market with the next killer Web app, companies are developing new software at an unprecedented rate—at this point, an "Internet year" is probably even shorter than a dog year.

This explosive growth has been especially noticeable in the browser arena. The first browsers were limited to basic text and image display. As time and technology moved forward, these capabilities became more sophisticated. The past few browser versions have marked major progressions in their capabilities with such powerful additions as an Object Model, increased script language support, greater control over Web page appearance, and the ability to manipulate the client-side display on the fly.

This book includes coverage of both Microsoft Internet Explorer and Netscape Navigator. However, some of the chapters toward the end of the book cover technologies that are available only in Internet Explorer. But even these chapters examine how Netscape Navigator handles these technologies and provide work-arounds where possible. Differences between browsers will be mentioned where appropriate throughout the text, and Chapter 24 will cover techniques for making your pages work with a variety of browsers.

NOTE
Most standards for browsers and other Web-related technologies are developed by the World Wide Web Consortium (W3C), an independent standards body founded in 1994. The purpose of the W3C is to "realize the full potential of the Web" by developing common standards for the evolution of the World Wide Web. To find out more about the W3C and its work, visit the W3C Web site at www.w3.org.


What Is Dynamic HTML?

Contrary to how it is typically portrayed by the press, Dynamic HTML (DHTML) is not just one particular technology, language, or set of features. Instead, DHTML comprises a number of different technologies and describes how these technologies interact. In simple terms, DHTML allows you to use conventional HTML, script, a Document Object Model, absolute positioning, dynamic styles, multimedia filters, and a variety of other technologies to dynamically change how HTML displays text and graphics on a screen.

Making HTML Dynamic

There is no debating that Hypertext Markup Language (HTML) remains the most important display technology on the Web. Since its use became widespread during the mid-1990s, HTML has evolved and added many new features. (Part 1 of this book will cover HTML in detail.)

However, with a few minor exceptions (such as when special ActiveX controls are used or form fields are changed), HTML pages are static; generally, the only way to change a screen display with HTML alone is to load another page. Internet Explorer versions 4 and 5, however, support an extensive Document Object Model that exposes all the elements of a page, including the HTML elements. This allows any HTML element in Internet Explorer to be manipulated at any time, even if the page has already been loaded, turning plain, old HTML into Dynamic HTML. The Netscape Navigator Object Model is not as complete as that of Internet Explorer, though it does allow some degree of manipulation. In both browsers, this manipulation is accomplished through scripts.

Tying Things Together with Scripts

You can accomplish a great deal on a Web page without ever having to write a line of script code. But to really take advantage of the power and features available in a Web browser, you'll probably want to learn a bit of scripting. We have to warn you, however, that scripting can be habit-forming. Once you see how effective scripts are and what they can add to your Web pages, you'll have a difficult time going back to unscripted pages! Many nonprogrammers think that scripting is too difficult to learn and use. While we agree that scripting can seem complex, we will show you how even simple scripts let you take advantage of powerful features of a Web browser.

For example, let's say that you have a Web page containing the image shown on this screen.

Click to view at full size.

If you want to change the image using just HTML, your only real option is to go to another page that displays a new image. With Dynamic HTML, you can change the image simply by changing the attributes of the HTML image tag. This would allow us to create a page in which the light bulb could be turned on by just clicking it. (To see this example in action, go to chap01\bulbtest.htm on the companion CD.)

Click to view at full size.

Notice that the image changes without refreshing the page. We constructed this example using only Dynamic HTML and a simple script. It contains no new tags, no Java code, and no ActiveX controls, just HTML and a small amount of script.

Scripting is especially important in version 4 browsers. In earlier versions, you could use scripting for certain objects and elements, but the list was relatively small. In versions 4 and later, many more elements are exposed as objects and, therefore, are available to scripts. JavaScript-compatible languages (such as Microsoft's JScript and Netscape's JavaScript) and Microsoft's Visual Basic Scripting Edition (VBScript) are two types of scripting languages commonly found on Web pages and supported in some Web servers. Scripts are usually embedded in the HTML on a Web page and are downloaded with the page. You can also detach scripts to a separate file and link them to pages when and where they are needed, allowing those scripts to be used and reused. (The chapters in Part 2 provide a more in-depth look at scripting, focusing on Microsoft's standards-based scripting language, JScript.)

Controlling Page Layout with Cascading Style Sheets

Putting pages up on the Web has long been referred to as Web "publishing." But you'll find quite a difference between Web publishing and its paper-based cousin, especially when it comes to page layout. Page layout on the Web, or in Web terminology the page's "look and feel," traditionally has been limited at best. Now modern browsers give authors and designers a much finer degree of control over how various elements—especially text—appear on the screen. This is accomplished through the use of Cascading Style Sheets (CSS) technology, which was introduced in Internet Explorer 3 and Netscape Navigator 4. Microsoft's implementation of CSS is known as dynamic styles. Style sheets give the content developer much greater control over almost every aspect of layout and formatting, including:

  • Fonts

  • Color

  • Borders

  • Backgrounds

  • Alignment

  • Absolute position

  • Leading (line spacing)

  • Effects (such as drop shadow and glow, Internet Explorer only)

Figure 1-1 shows an example of text formatting that you can set up with plain HTML. Although some text control is possible, it is very limited compared to what you can do with dynamic styles, as shown in Figure 1-2 on the following page. With dynamic styles, you can apply absolute positioning to elements on a page, add filters, and change character spacing. (You can find the HTML code for this demonstration of styles in chap01\styles.htm on the companion CD.) Dynamic styles also allows the content developer to change style attributes for elements after the page has been loaded. This lets you create such effects as collapsible menus and moving objects on the page.

Fortunately, CSS is not only for text. You can apply style attributes to other objects as well, from the type of border on a table to the visibility of an image. Part 3 of this book offers a detailed discussion of text and page layout using CSS.

Click to view at full size.

Figure 1-1. Text formatting in HTML.

Click to view at full size.

Figure 1-2. Dynamic styles using Cascading Style Sheets.

Using Internet Multimedia

Displaying multimedia elements on a Web page isn't new to the latest browser versions; you could do it in previous versions by using ActiveX controls, Java applets, basic built-in tools, or special plug-ins. However, Microsoft has added features to Internet Explorer 4 and 5 that have changed multimedia on the Web because the browser software itself includes or will automatically download a wide variety of controls necessary for using high-quality multimedia. Part 4 of this book will cover both cross browser and Internet Explorer_specific multimedia techniques. Here is a list of the multimedia components found in the latest versions of Internet Explorer and what they do:

  • Media Player This media control lets you add audio, video, ASF (Advanced Streaming Format) streaming video and audio, and other media to your page. It provides a full range of VCR-type controls, including Play, Stop, and Pause. It can be used with or without its built-in control bar.

  • Cascading Style Sheets Filters and Transitions Although you will use CSS most often for text, multimedia filters and transitions are part of dynamic styles and can be applied to many types of objects, including graphics, videos, and even the page itself. See Part 3 for details on how to use CSS.

  • Structured Graphics control With this control, you can create complex, lightweight, and scalable vector graphics. These graphics add little to file size and can be rotated in 3-D space, providing cool effects on a page while using very little bandwidth.

  • Sequencer control You can incorporate precise timing and lightweight animation with the Sequencer control. It lets you determine the timing of various events on a page with very fine control through scripts.

  • Path control This control allows you to move elements around on a page over time. A path can be as simple as a straight line or as complex as an intricate pattern. Combine the Path control with other multimedia controls for some impressive effects that won't take forever to download.

  • Sprite control This control allows you to build animation into your page by manipulating images with frame-level control. The frames can be individual images or a section of an image source that allows multiple images to be part of one file.

You can find a detailed discussion of these technologies in Part 4 of this book.

A key feature of all the multimedia components is that they are scriptable. All the multimedia that you put on a page can be authored and played back by using HTML code and script code. This capability is the key to true Internet multimedia. Because all the information needed to render the multimedia elements is coming from HTML or from script, pages that contain these elements can be very small and will download quickly.

Additional Technologies

Many other cool technologies are now available on the Web, ranging from scriptlets and behaviors to data binding and XML (Extensible Markup Language). Part 5 of this book explores in depth these technologies and other useful topics, such as techniques for enabling your pages to work on different versions of different browsers that do not support the same features. Let's take a quick look at one of these technologies: data binding. Before DHTML, just about any data that appeared on a Web page was pulled from the server and remained static. For example, suppose you looked at a Web site that displayed information about trees based on each tree's type and average height, as shown here.

Click to view at full size.

If you wanted to view only a list of trees that are of medium height, you would select the criterion Medium from the Sort By list and send the request. A server would receive the request, do some data processing, and then send back a page with a list of trees that are of medium height. If you then wanted to see only trees that are of the deciduous type, you would have to send a new query back to the server. The server would then process the query and send a new set of results. A server needed to be involved every time you wanted a new view of the information.

Internet Explorer 4 and later, however, can reduce a significant amount of this traffic by supporting what is known as data binding. The data binding function lets Web authors and developers attach, or bind, data directly to a page. Users can then modify views of the data without having to go back to the server with a request. As a user, you can get all your tree information with one request to the server and then sort or filter it in as many ways as you like. For instance, the illustration below shows the tree data filtered for medium height.

Click to view at full size.

To see this demo, open chap01\treedemo.htm on the companion CD. Notice that the page is loaded only once, although the data can be viewed in many different ways. We will look at data binding in more depth in Part 5.


Who Should Use Dynamic HTML?

If you publish information on the Internet, on an intranet, or even on CD-ROM—in other words, if you are a content developer or a content provider—you can benefit from using Dynamic HTML. Of course, content developer and content provider are terms that can apply to just about anyone. Here are some examples:

  • Individuals who want to build really cool professional or personal Web pages

  • Multimedia developers who want to present content through a browser rather than through a proprietary authoring tool

  • Webmasters who are seeking to enhance their company's Web site with more sophisticated "active" pages

  • C++ or Java developers who want to integrate Internet technologies into their programs

  • Network administrators or MIS managers who are looking at intranet technologies to replace some of their current high-cost, high-maintenance, distributed applications

  • Small-business owners who want to use intranet technologies within their companies

Whether you already have content on the Web or you are looking at Web technologies for the first time, Dynamic HTML has something for you.

Some Alternate Uses for Dynamic HTML

Most people use Dynamic HTML as a delivery mechanism for content on the Web. However, there are many other situations in which it can be used. For example, we have seen DHTML used (or have used it ourselves) for help documentation distributed with applications; for high-impact, CD-based multimedia training software; and with sophisticated distributed applications. Some of this cross-functional use is due to practical and flexible features of Internet Explorer: in addition to being a Web browser, it can also be hosted as a component in other applications, acting as a display engine. For instance, you can use Internet Explorer to build a CD-ROM_based multimedia title, integrate it into an HTML editing application as a Preview panel, or build an application with a user interface written partly in C++ and partly in HTML. The specifics of how to accomplish these tasks are beyond the scope of this book; however, a great resource for Web developers is the Site Builder Network (SBN) Web site, where you can find tons of practical information such as downloadable tools and examples, articles on the latest site construction techniques, and online experts and training. An important part of the SBN Web site is the SBN Workshop, which includes extensive source material and references on a variety of topics, including attributes supported by HTML tags and details about XML and Web site design. The companion CD includes a snapshot of the SBN Web site. To get to the online version of the Workshop, go to microsoft.com/workshop/default.asp

.


Let's Go!

Now you are ready to dig in and get your hands dirty. Roll up your sleeves, because the rest of this book will get you working with Dynamic HTML. Soon you'll be doing things once thought impossible on the Web. The rest of this section explores the specifics of using basic HTML to create your own Web pages.


Chapter 2 -- The Basics of HTML

 Chapter 2

The Basics of HTML

Hypertext Markup Language (HTML) is the core technology that controls what any Web browser displays on screen. Regardless of how well you know other Web technologies, you'll find it impossible to create dynamic Web pages without an understanding of HTML.

HTML was originally designed so that scientists could create text-based documents containing both basic formatting commands (known as markup) and links to other information (known as hypertext or hyperlinks). For instance, a document about earthquakes could contain a link to another document about plate tectonics written by a different scientist. The creators of HTML had no idea that this technology would prove so powerful and useful that it would be the major cause of growth for the Internet, and in turn, the World Wide Web.


Tag Basics

At its core, an HTML document is simply a plain text file containing special codes, called tags, that are usually placed around blocks of text. These blocks and the tags that surround them are called elements. A Web browser such as Microsoft Internet Explorer interprets, or parses, these elements to determine what to display on the screen. In most cases, each element has an opening tag and a closing tag. An opening tag consists of the tag name surrounded by angle brackets (the "<" and ">" characters). For example, the boldface opening tag is defined as <B>. A closing tag is also enclosed by angle brackets, but in this case a forward slash precedes the tag name: </B>. The affected text appears between the opening tag and the closing tag: when processed by the browser, the text between a <B> tag and its closing </B> tag is displayed in boldface.

To see how tags are used, let's analyze a basic Web page. Code Listing 2-1 presents some simple code that you might use to create such a page, and Figure 2-1 shows how Internet Explorer displays this code. (Remember that all of this book's code listings and sample files can be found on the companion CD.)

Code Listing 2-1.

<HTML>
<HEAD>
<TITLE>Listing 2-1</TITLE>
</HEAD>
<BODY>
Yet another "Hello World!"
</BODY>
</HTML>

HTML Container Tags

The first tag in Code Listing 2-1, <HTML>, indicates to the browser that the following material should be processed using the syntax and structure rules established for HTML. The corresponding closing tag, </HTML>, appears at the end of the file. You should not place anything outside these two tags, because the results can be unpredictable.

Click to view at full size.

Figure 2-1. A basic Web page.

Header Tags

The <HEAD> and </HEAD> tags mark the boundaries of the header region of the file, which contains items that are not directly rendered or displayed on the page. The header is optional, although the HTML specifications state that some elements should be used only inside it. TITLE is one such element. The <TITLE> and </TITLE> tags define what appears in the browser's title bar (the blue area above the menu bar). Because Internet Explorer (like most browsers) automatically adds its own name to the title, the document shown in Code Listing 2-1 will be titled Listing 2-1 - Microsoft Internet Explorer.

Body Tags

The next region indicated in Code Listing 2-1 is enclosed by the <BODY> and </BODY> tags. As you might expect, this area is known as the body of the document, and it contains the document's contents—the material that is visible on the page. Thus, our example displays the text Yet another "Hello World!"

Character Formatting Tags

If the preceding example represented the limits of HTML, the Web would be a pretty boring place. But you can get a little more creative and change the appearance of text with character formatting tags, as shown in Code Listing 2-2 and in Figure 2-2.

Code Listing 2-2 contains a variety of basic character formatting tags. In the first line, the bold tags <B> and </B> surround the words bold text—and these words appear in boldface in Figure 2-2. In the next line, the <I> and </I> tags italicize the words italic text. Several other character formatting tags are shown, including <U> for underlining, <STRIKE> for strikethroughs, <KBD> for fixed-width type, and <SUB> and <SUP> for subscripts and superscripts.

Code Listing 2-2.

<HTML>
<HEAD>
<TITLE>Listing 2-2</TITLE>
</HEAD>
<BODY>
This is some <B>bold text</B>.
This is some <I>italic text</I>.
This is some <U>underlined text</U>.
This is some <STRIKE>strikethrough text</STRIKE>.
This is some <KBD>fixed-width text</KBD>.
This is some <SUB>subscripted text</SUB>.
This is some <SUP>superscripted text</SUP>.
</BODY>
</HTML>

You can use the <FONT> tag to set up much more complex text formatting. This tag supports a variety of attributes, including COLOR, SIZE, and FACE, which detail exactly how the tag works. Many other tags support attributes, sometimes known as parameters.

In Code Listing 2-3, the first <FONT> tag illustrates the use of the COLOR attribute, which allows you to change the color of text. The COLOR attribute supports a huge range of colors, from AliceBlue to YellowGreen. You can find a full list of these named color values in the Color Table on the SBN Workshop Web site and on the CD that accompanies this book. (On the CD go to Workshop (References); DHTML, HTML & CSS; DHTML Object Model; References, and then choose Color Table in the content frame. To get to the online version, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm , or open the file named MSDN_OL.htm on the companion CD, and choose Color Table.) The COLOR attribute also supports hexadecimal triplet RGB values, which means that you can specify colors using hexadecimal numbers (such as #0000FF). Don't worry if you aren't familiar with this method—the Color Table lists just about any color you might want, as well as its hexadecimal equivalent.

The next <FONT> tag includes the SIZE attribute, which lets you change the relative size of the text. You can set text size on a scale of 1 to 7, with 7 being the largest. These numbers do not correspond to any specific point or pixel size, and the same size setting can vary in appearance on different systems. (You can gain much more precise control by using Cascading Style Sheets (CSS), as you will see in Part 3.)

Click to view at full size.

Figure 2-2. A page with sample character formatting.

NOTE
In this book, HTML tags are shown in all uppercase letters for readability: <TITLE>, for instance. You do not need to follow this convention when coding your own pages since HTML is not case sensitive. In other words, <BODY> is equivalent to <Body> and <body>. However, certain other technologies that Internet Explorer supports, such as Microsoft JScript, are case sensitive. JScript is discussed in Part 2 of this book.

Code Listing 2-3.

<HTML>
<HEAD>
<TITLE>Listing 2-3</TITLE>
</HEAD>
<BODY>
<FONT COLOR="blue">Color!</FONT>
<FONT SIZE="5">Size!</FONT>
<FONT FACE="Courier">Typeface!</FONT>
<FONT SIZE="6" COLOR="blue" FACE="Arial">Many Changes!</FONT>
</BODY>
</HTML>

The third <FONT> tag in Code Listing 2-3 uses the FACE attribute to change the typeface (font) of the text. In general, it is a good idea to use the default font (which means not to specify a font face in this tag at all) because it is often hard to predict what fonts are available on an end user's machine. This is especially true for situations like the Web, in which users' platforms can range from Microsoft Windows NT on a PC to MacOs on a Macintosh or Solaris on a Sun. Some commonly available fonts include Arial, Courier, and Times. (Internet Explorer 4 and 5 support a technology called font embedding, which allows you to include fonts that users can download along with your Web page; see Chapter 12 for more information.)

Click to view at full size.

Figure 2-3. Formatting characters with the <FONT> tag.

In HTML, a single tag can have multiple attributes. For instance, the final <FONT> tag in Code Listing 2-3 produces large blue text in the Arial typeface because its SIZE attribute is set to 6, its COLOR attribute to blue, and its FACE attribute to Arial. The attributes could have been listed in any order with the same results.

Line Formatting Tags

You might be surprised to see that Internet Explorer renders the separate lines of HTML in Code Listing 2-3 as one continuous line of text that wraps only when it reaches the edge of the browser window (Figure 2-3). HTML standards state that browsers should ignore line endings (linefeeds and carriage returns) in the source text file. (To be specific, each one is treated as a single whitespace, which refers to any character that appears as a blank space on a computer screen or printer. This includes the tab character, the space character, and other special characters. Sequential whitespaces are also treated as single spaces.) Instead, special tags are used to determine line formatting, as shown in Code Listing 2-4. Figure 2-4 shows the result of Internet Explorer processing this code.

The <P> and </P> tags in the first two lines of the body in Code Listing 2-4 define a block of text as a paragraph. As you can see in Figure 2-4, the tags cause each paragraph to be preceded and followed by a blank line.

The closing </P> tag is optional; if Internet Explorer encounters a new <P> tag, it automatically ends the previous paragraph. Thus, Internet Explorer displays the HTML code

<P>This is a paragraph.</P>
<P>This is another.</P>
<P>

in the same way it displays the following code, which has no closing </P> tags:

<P>This is a paragraph.
<P>This is another.
<P>

Both of these code snippets generate identical results.

The next two lines in Code Listing 2-4 demonstrate level-one and level-two headings. Like a paragraph, a heading has space before and after it. Each heading level is associated with a specific font size. HTML defines six levels of built-in headings; level-one headings are displayed as very large and level-six headings as very small. The different heading tags are not dependent on one another; thus, a level-three heading can be on its own, not preceded by a level-one or level-two tag.

The final lines of Code Listing 2-4 demonstrate the break tag, <BR>. This tag inserts a line break, but unlike the <P> tag it doesn't insert any extra blank lines. You don't need to add a closing </BR> tag because a break does not define a region of text. Rather, the browser breaks the line as soon as it encounters the <BR> tag. You can use multiple <BR> tags to insert multiple line breaks. This is an easy, although crude, method of creating custom spacing between lines.

Code Listing 2-4.

<HTML>
<HEAD>
<TITLE>Listing 2-4</TITLE>
</HEAD>
<BODY>
<P>This is an example of a paragraph.</P>
<P>This is another paragraph.</P>
<H1>This is a level-1 heading.</H1>
<H2>This is a level-2 heading.</H2>
This is not followed by a break.
This <B>is</B> followed by a break.
<BR>
This is not followed by a break.
This is not followed by a break.
</BODY>
</HTML>

NOTE
Part 3 of this book explains the use of Cascading Style Sheets (CSS), a relatively new standard that allows precise control over virtually all formatting, from alignment and margin width to the color and size of text. CSS has taken the place of the FONT tag on many Web sites.

Click to view at full size.

Figure 2-4. A page containing line formatting tags.

There may be times when you want to force the Web browser to ignore its whitespace rules and break the lines of text where your code has line breaks and put spaces where you have spaces. This is accomplished with the <PRE> tag, shown in Code Listing 2-5, which tells the browser that you have preformatted the upcoming text.

Code Listing 2-5 also demonstrates the horizontal rule tag, <HR>, which creates a horizontal line, or rule, across the page. Two common attributes used with the <HR> tag are SIZE and WIDTH. SIZE determines the thickness of the rule in pixels, which can vary from 1 to 100 pixels. The default SIZE is 2. WIDTH controls the width of the rule, which you can set to a specific number of pixels or to a percentage of the available space on the screen. Thus, <HR WIDTH="50"> creates a horizontal rule that is 50 pixels wide, while <HR WIDTH="50%"> draws a rule that is 50 percent of the width of the browser window. The default width is 100 percent. Finally, in Code Listing 2-5 we see an example of the no-break tag, <NOBR>. Anything inside a <NOBR> element will not break at the end of a line. This can be very helpful if you want to keep words or graphics together on the same line. For example, there might be a legal requirement for a product's name to be displayed entirely on one line.

Code Listing 2-5.

<HTML>
<HEAD>
<TITLE>Listing 2-5</TITLE>
</HEAD>
<BODY>
<PRE>
This is an example of some
    preformatted text.
Notice how     the page
 is displayed with the same spacing and
   line breaks as the code.
</PRE>
<HR>
<HR WIDTH="50%" SIZE="6">
One of these lines uses no-break and one does not.
<NOBR>One of these lines uses no-break and one does not.</NOBR>
</BODY>
</HTML>

Figure 2-5. Examples of preformatted text, horizontal rules, and the no-break tag.

NOTE
A warning about using the <PRE> tag: browsers normally wrap text automatically when a line is longer than the browser's display window. When using <PRE>, however, this does not occur. Thus, incautious use of preformatted text can result in pages that require the user to scroll horizontally to view all the text, as shown in Figure 2-5.

NOTE
An <HR> tag with a 100 percent width normally will not take up the entire width of the screen. Typically, there is a small margin on each side of the rule. You can correct this (as well as other cases in which you want content to reach to the edge of the screen) by reducing the margins on the <BODY> tag. The horizontal margins can be eliminated by setting the LEFTMARGIN attribute of the <BODY> tag to 0. The vertical margins can be eliminated with the TOPMARGIN attribute. Thus, the following <BODY> tag would completely eliminate margins around the page.

<BODY LEFTMARGIN="0" TOPMARGIN="0">

You can also increase the margins around the page by increasing the values of these attributes.

Alignment Attributes and Tags

HTML also lets you control the horizontal position of elements on the page. Code Listing 2-6 demonstrates two methods. Figure 2-6 shows the results.

Code Listing 2-6.

<HTML>
<HEAD>
<TITLE>Listing 2-6</TITLE>
</HEAD>
<BODY>
<P ALIGN="left">This text is left-aligned.</P>
<H2 ALIGN="center">This text is centered.</H2>
<H5 ALIGN="right">This text is right-aligned.</H5>
<CENTER>This text is also centered.</CENTER>
</BODY>
</HTML>

By default, Web browsers align all text along the left side of the screen (left-aligned). One way you can change this is by using the ALIGN attribute. Several tags support the ALIGN attribute, including <P> and all the heading tags. In the first three lines in the body of Code Listing 2-6, ALIGN is used to left-align text, center it on the screen, and right-align it. Because centering text is extremely common, this action has its own tag, <CENTER>, as you can see in the last line of the body. The browser will center on the page any text between the <CENTER> and </CENTER> tags.

Click to view at full size.

Figure 2-6. A page showing various text alignments.

Image and Hyperlink Tags

Images and hyperlinks provide some of the most powerful benefits of HTML. Internet Explorer allows you to display a variety of graphics types, the most common being GIFs and JPEGs (Graphics Interchange Format and Joint Photographic Experts Group, two widely used graphics file formats). A hyperlink defines a region of the screen that the user can click to go to another Web page or to a specific place on the same page. Code Listing 2-7 contains both images and hyperlinks, which are displayed in Figure 2-7.

Code Listing 2-7.

<HTML>
<HEAD>
<TITLE>Listing 2-7</TITLE>
</HEAD>
<BODY>
Here is an image <IMG SRC="sample.gif" WIDTH="20" HEIGHT="36">.
<BR>
<IMG SRC="sample.gif" WIDTH="20" HEIGHT="36" ALIGN="right">
This image has been given an alignment. This causes the image to
be removed from the flow of the text and displayed at a particular
location relative to the surrounding text.
<BR>
Here is a <A HREF="http://www.microsoft.com">link to Microsoft</A>.
<BR>
The next link has a picture and text and links to a local file.
<BR>
<A HREF="other.htm"><IMG SRC="sample.gif"> text</A>
<BR>
This final link points to a bookmark in the file "other.htm".
<BR>
<A HREF="other.htm#bookmark1">Link to bookmark</A>
</BODY>
</HTML>

Click to view at full size.

Figure 2-7. A page containing images and links.

The <IMG> tag is used to place an image on a page. The closing tag </IMG> is optional and is almost never used. An image is an in-line element by default, which means that it moves along with any text, just as a word does. Inclusion of an image affects the way lines wrap, and the image itself is affected by settings that influence text, such as margins.

The <IMG> tag has a variety of attributes that define how an image is displayed. The most important is the SRC attribute, which contains a path to the source graphics file. In Code Listing 2-7, we used the name of a local graphic (one that is stored in the same directory as the HTML file). You can also set the SRC attribute to point to graphics files in other locations, such as another directory on the same computer or a graphics file on another Web site. To do this for another directory, simply include the path before the name of the graphic: for example, graphics/sample.gif. For another Web site, provide the full Web location of the file, preceded by http://: for example, http://www.microsoft.com/library/images/gifs/logos /ieget_animated.gif. The http:// tells the browser to access the file using HTTP (Hypertext Transfer Protocol), which is used to transfer most files over the Web.

Two other attributes commonly used in <IMG> tags are WIDTH and HEIGHT. Both are expressed in pixels. If you do not specify a width and height, the browser will display a default placeholder graphic of a fixed size until it has downloaded the specified image. The image will then be correctly sized, usually causing the text on the screen to reflow. Specifying values for the WIDTH and HEIGHT attributes allows the browser to reserve space on the screen before the actual images are downloaded. This method offers a significant advantage to users who have slow Internet connections because it enables their browsers to display correct page layouts quickly. Setting the WIDTH and HEIGHT attributes to values other than the true width and height of an image causes the browser to scale the image to the dimensions specified.

The second <IMG> tag in Code Listing 2-7 demonstrates the ALIGN attribute. This attribute causes the image to no longer be displayed in line with the text. Instead, the image is displayed at a particular location relative to the text that follows it. Valid values for ALIGN include top, bottom, middle, left, and right, which do exactly what you would expect. Less obvious values are absbottom, absmiddle, baseline, and texttop, which give greater alignment control by incorporating information specific to the font being used when calculating where to position the image. Many other elements support the ALIGN attribute, including TABLE (covered in Chapter 3) and FIELDSET (covered in Chapter 4).

Code Listing 2-7 also illustrates the use of hyperlinks. A hyperlink is enclosed by the anchor tags <A> and </A> and is usually formatted as blue and underlined. When the user moves the mouse over a hyperlink, the mouse pointer changes to a pointing hand. Clicking the link causes Internet Explorer to open up the page specified in the link.

The anchor tag supports an HREF (hypertext reference) attribute, which defines the location the browser should go to. This location can be any valid Web location; for the first hyperlink in Code Listing 2-7, we chose http://www.microsoft.com. If we had not preceded the location with http://, the browser would look on the current server for a folder named www.microsoft.com, which does not exist. You can also set the HREF attribute to a local file, as we did in the second anchor in the sample. Setting the location to other.htm causes the browser to try to open a file named other.htm in the same directory as our sample file. If we had set the location to more/other.htm, the browser would have looked for other.htm in a more subdirectory of the directory that contains our sample file.

NOTE
Notice that the hyperlinked image is displayed with a blue border around it. This is not necessary, and designers frequently do not want such a border to be displayed. You can disable it by setting the BORDER attribute of the IMG element to 0. Conversely, if you would like to show the image with an even larger border, you can set the BORDER attribute to larger values, such as 15 or even more.

It is also possible to reference a named bookmark on a page, a technique often used in large documents. The last anchor in Code Listing 2-7 contains such a reference. When it is clicked, Internet Explorer opens the other.htm file and then scrolls through until it reaches the specified bookmark.


Constructing Lists

HTML includes a set of tags that allow the creation of hierarchical bulleted lists. There are two types of lists: unordered and ordered. Unordered lists are bulleted, whereas ordered lists are usually numbered. You can also combine the two types to create more complex lists.

Unordered Lists

First let's take a look at two unordered lists. The code for these appears in Code Listing 2-8. Figure 2-8 displays the lists, separated by a horizontal rule.

Code Listing 2-8.

<HTML>
<HEAD>
<TITLE>Listing 2-8</TITLE>
</HEAD>
<BODY>

<UL>This is at the first level.
  <UL>This is at the second level.</UL>
  <UL>This is at the second level.
    <UL> This is at the third level.</UL>
  </UL>
  <UL>This is at the second level.</UL>
</UL>

<HR>

<UL>This is the first level header.
  <LI>This is the first level-1 item in the list.
  <LI>This is the second level-1 item in the list.
  <UL>
    <LI>This is the first level-2 item in the list.
    <LI>And this is the second level-2 item in the list.
  </UL>
  <LI>This is the third level-1 item in the list.
</UL>

</BODY>
</HTML>

Click to view at full size.

Figure 2-8. An example of an unordered list.

NOTE
HTML ignores extra white space. Notice how the code in Code Listing 2-8 takes advantage of this feature by using indents to visually separate the levels of hierarchy in the list. Though unnecessary, indenting lines of code can be a powerful debugging tool because it makes it easy to immediately recognize such common mistakes as accidentally leaving out a tag.

The first list in Code Listing 2-8 is constructed using only the unordered list tags, <UL> and </UL>. By placing one set of unordered list tags within another, we can embed lists within one another to create a series of indented pieces of text. Notice that each opening <UL> tag has a paired closing </UL> tag.

The next list shown in Code Listing 2-8 also begins with the unordered list tag, <UL>. A closing tag, </UL>, is necessary, and it appears at the end of the list, toward the end of the file. Anything between these two tags is considered part of the list. This list contains bulleted line items, preceded by the list item tag, <LI>. The ending tag, </LI>, is not required since anything encountered before another item begins or before the end of the list is considered part of the current list item. Another list is embedded in this list. Notice that this embedded list is indented and that its bullets have a different shape. Only the first three levels of embedding have differing types of bullets. Beginning with the third level, all lists use the same style bullet. Notice that the second level does not have any text after the <UL>. Such header text is optional.

Ordered Lists

The line items of an ordered list are displayed with numbers rather than with bullets. Use the <OL> tag to set up an ordered list, as shown in Code Listing 2-9. Figure 2-9 shows how Internet Explorer displays this code.

Code Listing 2-9.

<HTML>
<HEAD>
<TITLE>Listing 2-9</TITLE>
</HEAD>
<BODY>
<OL>
  <LI>This is the first level-1 item in the list.
  <LI>This is the second level-1 item in the list.
  <OL>
    <LI>This is the first level-2 item in the list.
    <LI>And this is the second level-2 item in the list.
  </OL>
  <LI>This is the third level-1 item in the list.
</OL>
</BODY>
</HTML>

Click to view at full size.

Figure 2-9.An example of an ordered list.

The list in Code Listing 2-9 begins with the ordered list tag, <OL>. As is the case with an unordered list, a closing tag (</OL>) is necessary. Each list item is now preceded by a number rather than by a bullet. Notice that a second list is embedded within the first and that the numbering restarts with 1 in this second list.

Complex Lists

The <OL> tag supports an attribute named TYPE, which controls whether the list items are prefaced with numbers, letters, or roman numerals. Code Listing 2-10 demonstrates the TYPE attribute as well as the mixing of <OL> and <UL> tags. You can see the display produced by this code in Figure 2-10. By combining ordered and unordered lists and by using the TYPE attribute, you can present complex hierarchical information.

Code Listing 2-10.

<HTML>
<HEAD>
<TITLE>Listing 2-10</TITLE>
</HEAD>
<BODY>
<OL TYPE="1">
  <LI>This uses numbers.
  <OL TYPE="A">
    <LI>This uses uppercase letters.
    <OL TYPE="a">
      <LI>This uses lowercase letters.
      <OL TYPE="I">
        <LI>This uses uppercase roman numerals.
        <OL TYPE="i">
          <LI>This uses lowercase roman numerals.
          <LI>This also uses lowercase roman numerals.
        </OL>
      </OL>
    </OL>
  </OL>
  <UL>
    <LI>Here is a bullet.
  </UL>
</OL>
</BODY>
</HTML>

Click to view at full size.

Figure 2-10. An example of a complex list.

By now, you should feel comfortable with some of the commonly used elements in HTML. In the next chapter, we explore two of the most powerful layout tools provided by HTML—tables and frames.


Chapter 3 -- Tables and Frames

 Chapter 3

Tables and Frames

A well-organized Web page provides users with a good browsing experience and makes it easy for them to find the information they want. Tables and frames are valuable tools for organizing information. With tables, you can subdivide parts of a Web page into regions and place different types of content in each region. You'll find that tables are useful for a variety of tasks, from presenting data in columns and rows to precisely positioning items on a page.

Frames allow a browser to display multiple HTML files on the screen at the same time, each in its own defined area. When you use frames, you can keep a file visible in one location in the window while changing the files being displayed in other locations. This capability can be helpful when you are building a Web site in which you want one page, such as a banner or an index, to remain visible while another part of the screen displays different or changing information.


Tables

You can use tables for far more than simply presenting data in tabular form. They are one of the most powerful page layout tools available in HTML. The tags used to make tables are also rich in features, supporting everything from colored borders and backgrounds to the vertical and horizontal alignment of table contents.

Table Basics

Tables are marked by the tags <TABLE> and </TABLE>. Inside these tags, you use table row tags, <TR> and </TR>, to define rows of data. Within each row, cells are defined by table data tags <TD> and </TD>. Code Listing 3-1 presents a page containing a basic table. You can see the table produced by this code in Figure 3-1.

Setting the BORDER attribute to 1 creates a 1-pixel-wide border around each cell as well as around the whole table. If you increase this value, the thickness of the table border increases, although the line around each cell remains 1 pixel wide. (The following section discusses several other attributes that format the space between cells.)

NOTE
Because HTML ignores extra white space, we were able to use indents in Code Listing 3-1 to visually separate the different levels of the table. The <TD> tags are indented further than the <TR> tags, which are indented further than the <TABLE> tags. It isn't necessary to use indents, but we highly recommend this technique for its usefulness as a debugging tool, especially in more complex tables.

Code Listing 3-1.

<HTML>
<HEAD>
<TITLE>Listing 3-1</TITLE>
</HEAD>
<BODY>
<TABLE BORDER="1">
  <TR>
    <TD>R1, D1</TD>
    <TD>Row 1, Data 2</TD>
  </TR>
  <TR>
    <TD>Row 2, Data 1</TD>
    <TD>This is Row 2, Data Column 2</TD>
  </TR>
</TABLE>
</BODY>
</HTML>

Click to view at full size.

Figure 3-1. A basic table.

More Table Attributes

Table tags have many attributes in addition to BORDER. Code Listing 3-2 below sets up two tables that illustrate some of the most common attributes, as shown in Figure 3-2.

We set the BORDER attribute to 5 for the first table and 10 for the second; notice the difference in thickness of the outside border around each table in Figure 3-2. The CELLPADDING attribute controls the amount of space between a cell's contents and the cell's boundary, whereas CELLSPACING controls the spacing between cells. The first table in Figure 3-2 shows a lot of space between cells (CELLSPACING is set to 15) but only a little space separating text from the edges of the cell in which it resides (CELLPADDING is set to 2). The second table contains only a small amount of space between cells but a lot around the cell contents.

You can also change the background of an entire table, including the cells, by changing the setting of the BGCOLOR attribute, which controls the background color. By default, the background is transparent. If you set different background colors for a table and for a cell within that table, the cell's color takes precedence.

In the first table in Code Listing 3-2 and Figure 3-2, we set the background color of the table to yellow, but we set the BGCOLOR attribute of the first cell in the second row to white. As a result, the only part of the table that is white is the interior of that one cell.

Code Listing 3-2.

<HTML>
<HEAD>
<TITLE>Listing 3-2</TITLE>
</HEAD>
<BODY>
<TABLE BORDER="5" CELLPADDING="2" CELLSPACING="15" BGCOLOR="yellow">
  <TR>
    <TD>R1,D1</TD>
    <TD>Row 1, Data 2</TD>
  </TR>
  <TR>
    <TD BGCOLOR="white">Row 2, Data 1</TD>
    <TD BACKGROUND="back.gif">This is Row 2, Data Column 2</TD>
  </TR>
</TABLE>
<HR>
<TABLE BORDER="10" CELLPADDING="15" CELLSPACING="2" BACKGROUND="back.gif">
  <TR>
    <TD>R1,D1</TD>
    <TD>Row 1, Data 2</TD>
  </TR>
  <TR>
    <TD BGCOLOR="white">Row 2, Data 1</TD>
    <TD>This is Row 2, Data Column 2</TD>
  </TR>
</TABLE>
</BODY>
</HTML>

Click to view at full size.

Figure 3-2. Two tables that illustrate basic table formatting.

The BACKGROUND attribute allows you to display an image behind a cell or an entire table; simply set this attribute to the path of the desired graphic. The last cell in the first table demonstrates a cell-only background, while the second table shows a full-table background image.

These are only the most common formatting attributes; many more are supported. The BORDERCOLOR, BORDERCOLORLIGHT, and BORDERCOLORDARK attributes let you fine-tune the appearance of borders. Attributes named FRAME and RULES control which sides of the outer and inner borders display. You can also create table headers and footers using tags such as <THEAD> and <TFOOT>, and you can organize the information within tables using the <TBODY> tag. The <CAPTION> tag can be used to label a table. (The SBN Workshop Web site and the CD that accompanies this book both fully describe all of these additional tags and attributes. On the CD go to Workshop (References); DHTML, HTML & CSS; HTML References, and then Elements. To get to the online version, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm , or open the file named MSDN_OL.htm on the companion CD, and choose HTML Tags and Attributes.) Some versions of Netscape Navigator (including versions 3 and 4) will have problems with several of the listed attributes, including BGCOLOR and BACKGROUND. These problems are most evident with version 3.

Cells of Variable Size

Not all cells in a table need to be the same size. For instance, some rows might require only two cells, while others need four. Some cells might need to be two or more rows tall. To accommodate this variability, HTML provides the COLSPAN and ROWSPAN attributes. Code Listing 3-3 and Figure 3-3 offer an example of how you can use the COLSPAN attribute.

Code Listing 3-3.

<HTML>
<HEAD>
<TITLE>Listing 3-3</TITLE>
</HEAD>
<BODY>
<TABLE BORDER="1">
  <TR>
    <TD COLSPAN="2" ALIGN="center">Row 1, Data 1</TD>
  </TR>
  <TR>
    <TD>Row 2, Data 1</TD>
    <TD>Row 2, Data 2</TD>
  </TR>
</TABLE>
</BODY>
</HTML>

Click to view at full size.

Figure 3-3. A table illustrating the use of the COLSPAN attribute.

The COLSPAN attribute specifies the width of a cell in columns. A cell normally fills one column. Setting COLSPAN to 2 causes a cell to span two columns; setting it to 4 creates a cell width of four columns. In Figure 3-3, you can see that setting COLSPAN to 2 causes the specified cell to be as wide as two of the cells in the adjacent row. Also notice that the ALIGN attribute has been set to center the contents of the cell. (Cell contents by default align to the left.) This technique of setting up a wide, center-aligned cell often comes in handy when you want to create a heading for a table.

Next let's take a look at a more advanced example of a table that uses both the COLSPAN and ROWSPAN attributes. Code Listing 3-4 contains the sample code; you can see the result that Microsoft Internet Explorer displays in Figure 3-4.

This example demonstrates two new techniques: the use of ROWSPAN and empty spacer cells. By setting the ROWSPAN attribute, you can create cells that are several rows tall, which is useful when you need to group types of data—in this case, apples and oranges. You can also use ROWSPAN and COLSPAN together to create cells that are both extra wide and tall, though we do not demonstrate this in the sample. Empty cells in the second row are denoted simply by a <TD> and </TD> tag pair, with nothing between the opening and closing tags. The Store 1 and Store 2 cells would have appeared at the far left of the row if we had not included these empty spacer cells.

Code Listing 3-4.

<HTML>
<HEAD>
<TITLE>Listing 3-4</TITLE>
</HEAD>
<BODY>
<TABLE BORDER="1">
  <TR>
    <TD COLSPAN="4" ALIGN="center"><B>Fruit Sales</B></TD>
  </TR>
  <TR>
    <TD></TD>
    <TD></TD>
    <TD>Store 1</TD>
    <TD>Store 2</TD>
  </TR>
  <TR>
    <TD ROWSPAN="2">Apples</TD>
    <TD>Day1</TD><TD>40</TD><TD>25</TD>
  </TR>
  <TR>
    <TD>Day2</TD><TD>30</TD><TD>30</TD>
  </TR>
  <TR>
    <TD ROWSPAN="2">Oranges</TD>
    <TD>Day1</TD><TD>40</TD><TD>25</TD>
  </TR>
  <TR>
    <TD>Day2</TD><TD>30</TD><TD>30</TD>
  </TR>
</TABLE>
</BODY>
</HTML>

Click to view at full size.

Figure 3-4. A table that illustrates the use of both the COLSPAN and ROWSPAN attributes.

Embedded Tables

An embedded table is exactly what you might expect: one table contained within, or embedded in, another. This technique provides a wide range of flexibility, allowing you to assign different background and border treatments to various parts of the table, and is often easier to use than ROWSPAN and COLSPAN. Code Listing 3-5 demonstrates the embedding of two smaller tables within a larger table. See Figure 3-5 to view how the listing is displayed.

Click to view at full size.

Figure 3-5. An example of embedded tables.

NOTE
Web browsers generally do not pay attention to where lines of code end in your HTML file. Because of this, we were able to combine several table data blocks (delimited by the <TD> and </TD> tags) into one line in Code Listing 3-4, saving space on the screen without sacrificing readability. You can see this in the row containing the Day1, 40, and 25 table data elements.

As you can see in Figure 3-5, the larger (outer) table in this example consists of two columns and two rows (four cells). The first and fourth cells in this table contain only simple numerical data (the numbers 1 and 2). The second and third cells, however, each contain a four-cell embedded table.

The code for the first cell also introduces a new attribute, VALIGN, which controls the vertical alignment of the contents of the cell. In this instance, we set VALIGN so that the cell contents appear at the top of the cell. In the fourth cell, we used both VALIGN and ALIGN to position the contents in the lower right corner of the cell. Also notice that we used the BORDER attribute to vary the width of the border around each table.

Code Listing 3-5.

<HTML>
<HEAD>
<TITLE>Listing 3-5</TITLE>
</HEAD>
<BODY>
<TABLE BORDER="1" CELLPADDING="5">
  <TR>
    <TD VALIGN="top">1</TD>
    <TD>
      <TABLE BORDER="2">
        <TR><TD>A</TD><TD>B</TD></TR>
        <TR><TD>C</TD><TD>D</TD></TR>
      </TABLE>
    </TD>
  </TR>
  <TR>
    <TD>
      <TABLE BORDER="5">
        <TR><TD>E</TD><TD>F</TD></TR>
        <TR><TD>G</TD><TD>H</TD></TR>
      </TABLE>
    </TD>
    <TD VALIGN="bottom" ALIGN="right">2</TD>
  </TR>
</TABLE>
</BODY>
</HTML>

NOTE
When you create embedded tables, the BORDER attribute can help with debugging. Regardless of whether your final product will contain borders, including them while you work allows you to see clearly where one table begins and another ends. This is important when you are creating complex tables that use COLSPAN and ROWSPAN, but especially so when you are creating multiple levels of embedding.

Tables as Layout Tools

Tables are perhaps the most important layout tool in conventional HTML. When you set the WIDTH and HEIGHT attributes for a table in combination with setting ALIGN and VALIGN attributes for cells, you can position items almost anywhere on a Web page. The code shown in Code Listing 3-6, for example, demonstrates how you can use a table to establish various regions on a page and specify that the regions contain different types of content. This example will dynamically resize as you resize your browser. Figure 3-6 shows how Internet Explorer displays the results.

Click to view at full size.

Figure 3-6. An example of using a table for page layout.

Code Listing 3-6.

<HTML>
<HEAD>
<TITLE>Listing 3-6</TITLE>
</HEAD>
<BODY TOPMARGIN="0" LEFTMARGIN="0">
<TABLE WIDTH="100%" HEIGHT="100%" CELLSPACING="0" CELLPADDING="5" BORDER="0">
  <TR>
    <TD COLSPAN="3" ALIGN="CENTER" BGCOLOR="black" HEIGHT="25">
      <FONT COLOR="white"><B>Page Using Tables</B></FONT>
    </TD>
  </TR>
  <TR>
    <TD BGCOLOR="thistle" WIDTH="70" VALIGN="top">
      <IMG SRC="trans.gif" WIDTH="70" HEIGHT="0" BORDER="0"><BR>
      <B>Listings</B><BR>
      <A HREF="lst3-1.htm">Listing 3-1</A><BR>
      <A HREF="lst3-2.htm">Listing 3-2</A><BR>
      <A HREF="lst3-3.htm">Listing 3-3</A><BR>
      <A HREF="lst3-4.htm">Listing 3-4</A><BR>
    </TD>
    <TD ALIGN="center">
      <IMG SRC="trans.gif" WIDTH="150" HEIGHT="0" BORDER="0"><BR>
      This page demonstrates using a table for page layout.<BR>
      It is organized with local links on the left, external links
      on the right, content in the center, and a header at the top.
    </TD>
    <TD VALIGN="top" WIDTH="25%" BGCOLOR="lightgrey">
      <IMG SRC="trans.gif" WIDTH="120" HEIGHT="1" BORDER="0"><BR>
      <B>Organizations</B><BR>
      <A HREF="http://www.microsoft.com">Microsoft</A><BR>
      <A HREF="http://mspress.microsoft.com">Microsoft Press</A><BR>
      <A HREF="http://www.w3.org">W3C</A><BR>
    <BR>
      <B>Useful Sites</B><BR>
      <A HREF="http://microsoft.com/Workshop">SBN Workshop</A><BR>
      <A HREF="http://msdn.microsoft.com/">MSDN</A><BR>
      <A HREF="http://www.webreference.com">WebReference.com</A><BR>
      <A HREF="http://www.webreview.com">WebReview.com</A><BR>
    </TD>
  </TR>
</TABLE>
</BODY>
</HTML>

The table's WIDTH and HEIGHT attributes can be set either to pixel values or to a percentage of the screen size. In Code Listing 3-6, we set both attributes to 100 percent, which means that the table will take up all the allowable space in the window. Normally, a small margin exists around the contents of an HTML page, but we removed this margin by setting the <BODY> tag's TOPMARGIN and LEFTMARGIN attributes to 0. (Unfortunately, Netscape Navigator does not completely honor these attributes and will still display a small amount of white space at the perimeter of the page.) To ensure that there are no gaps between cells, we set the CELLSPACING attribute to 0. By making the table fill the entire window, we can treat the page like a grid and place items anywhere on the page. CELLSPACING has been set to 5 to prevent the text in the table from running right up against the edges of the cells.

NOTE
Generally, we feel it is much better to use a percentage WIDTH setting for a layout table than a pixel WIDTH setting. When a specific pixel width is set for a table, users who have screen resolutions different from that of the Web page author often end up with odd Web page displays. For example, if you create a table 640 pixels wide, intending it to take up the entire width of a low resolution screen, a user with a screen resolution of 1280 by 1024 will see the table taking up only half of the monitor's width. Through careful application of percentage WIDTH settings and the use of the transparent image technique discussed later in this section, a table that takes full advantage of screens at any resolution can be created.

The sample table has two rows and three columns. The first row consists of a single cell with COLSPAN set to 3, which extends the cell across the screen. This cell is used for the header.

The next row contains three cells. The first cell is set to a width of 70, which makes the cell 70 pixels wide. One potential problem is that some early browsers might not respect the WIDTH attribute of a <TD> tag and, as a result, create a cell that is too narrow. Such browsers, however, will not create a cell narrower than the widest item in the cell. Because of this, a common workaround is to place within the cell an invisible element of the desired minimum width. This can be accomplished with a transparent GIF file, sized according to the desired width of the cell. The sample file uses trans.gif, a one-pixel tall, one-pixel wide graphic that is only .043 kilobytes in file size. By using this image in the bottom left table cell and setting its corresponding <IMG> tag's WIDTH and HEIGHT attributes, we have restricted the minimum width of the cell in a way that should work in all browsers. This cell also uses a VALIGN of top to set the contents to the top of the cell.

The next cell uses the ALIGN attribute to center the contents of the cell. Cell contents are left-aligned and vertically centered by default. Therefore, in this case it is not necessary to explicitly set the VALIGN attribute. Because this cell has no set WIDTH, it will assume the width remaining after the first and last cells have reserved their spaces.

The last cell specifies a width of 25%. As a result, and in contrast to the first cell in this row, this last cell will change in width if the browser is resized. Using an image of a set width guarantees that the cell will never be narrower than a particular desired value. This prevents problems if a user resizes the browser window to be very small.

When you use tables for page layout, remember that setting the BORDER attribute can be a big help when you need to troubleshoot. For instance, if we were trying to create the same effect as in Code Listing 3-6, we would find that the code in Code Listing 3-7 contains a mistake. On the screen display, shown in Figure 3-7, the borders help you see the error. The table clearly contains too much space between cells—and when you check the code, you find that CELLSPACING has been set to 10 instead of 0, causing the extra space.

Click to view at full size.

Figure 3-7. Using the BORDER attribute to troubleshoot tables.

NOTE
In the first column, we used an image sized to the minimum desired cell width in order to prevent the cell from getting smaller and causing the text in the cell to wrap undesirably. Instead of setting a minimum width, we could have prevented the text in the cell from wrapping in other ways. For example, we could have used the NOWRAP attribute on the <TD> tag for this cell. NOWRAP will prevent any text wrapping in a cell that is not explicitly set by the author. We also could have used a nonbreaking space character entity rather than a normal space after the word listing (listing&nbsp;3-1 instead of listing 3-1). This entity treats the word listing and the following number as one word, instead of two. You can learn more about character entities in Chapter 4.

Code Listing 3-7.

<HTML>
<HEAD>
<TITLE>Listing 3-7</TITLE>
</HEAD>
<BODY TOPMARGIN="0" LEFTMARGIN="0">
<TABLE WIDTH="100%" HEIGHT="100%" CELLSPACING="10" CELLPADDING="5" BORDER="1">
  <TR>
    <TD COLSPAN="3" ALIGN="CENTER" BGCOLOR="black" HEIGHT="25">
      <FONT COLOR="white"><B>Page Using Tables</B></FONT>
    </TD>
  </TR>
  <TR>
    <TD BGCOLOR="thistle" WIDTH="70" VALIGN="top">
      <IMG SRC="trans.gif" WIDTH="70" HEIGHT="0" BORDER="0"><BR>
      <B>Listings</B><BR>
      <A HREF="lst3-1.htm">Listing 3-1</A><BR>
      <A HREF="lst3-2.htm">Listing 3-2</A><BR>
      <A HREF="lst3-3.htm">Listing 3-3</A><BR>
      <A HREF="lst3-4.htm">Listing 3-4</A><BR>
    </TD>
    <TD ALIGN="center">
      <IMG SRC="trans.gif" WIDTH="150" HEIGHT="0" BORDER="0"><BR>
      This page demonstrates using a table for page layout.<BR>
      It is organized with local links on the left, external links
      on the right, content in the center, and a header at the top.
    </TD>
    <TD VALIGN="top" WIDTH="25%" BGCOLOR="lightgrey">
      <IMG SRC="trans.gif" WIDTH="120" HEIGHT="1" BORDER="0"><BR>
      <B>Organizations</B><BR>
      <A HREF="http://www.microsoft.com">Microsoft</A><BR>
      <A HREF="http://mspress.microsoft.com">Microsoft Press</A><BR>
      <A HREF="http://www.w3.org">W3C</A><BR>
    <BR>
      <B>Useful Sites</B><BR>
      <A HREF="http://microsoft.com/Workshop">SBN Workshop</A><BR>
      <A HREF="http://msdn.microsoft.com/">MSDN</A><BR>
      <A HREF="http://www.webreference.com">WebReference.com</A><BR>
      <A HREF="http://www.webreview.com">WebReview.com</A><BR>
    </TD>
  </TR>
</TABLE>
</BODY>
</HTML>


Frames

By using frames, you can break up the Web page into distinct regions and show a different HTML file in each. With this arrangement, one region can switch to another page while other regions remain the same. For instance, a page containing an advertising banner or a navigational menu (similar to a book's table of contents) can remain visible in one part of the browser window while the user jumps between pages in the site in another part of the window. Frames can be a tremendously valuable layout tool, but they can also present a variety of problems.

Frame Basics

You create frames by using a frameset document, a standard HTML file that simply contains information about how the page should be split and which files should be displayed in each region. Code Listing 3-8 is the HTML code for a basic frameset document; Figure 3-8 shows the document displayed by Internet Explorer.

NOTE
Notice that the document created in Code Listing 3-8 does not include a body region. To avoid potential problems, HTML standards dictate that an HTML file can have either a frameset or a body but not both. Older versions of Internet Explorer supported a body in the same document as a frameset, but Microsoft removed this functionality in Internet Explorer versions 4 and 5 to adhere more closely to the W3C standards.

Code Listing 3-8.

<HTML>
<HEAD>
<TITLE>Listing 3-8</TITLE>
</HEAD>
<FRAMESET COLS="50%,70,*">
  <FRAME SRC="1.htm">
  <FRAME SRC="2.htm">
  <FRAME SRC="3.htm">
</FRAMESET>
</HTML>

The frameset in Code Listing 3-8 points to three documents that exist on the companion CD named 1.htm, 2.htm, and 3.htm. Inside the <FRAMESET> tag, we included the COLS attribute, which indicates that the page will be divided into columns. The attribute's three settings specify three columns: the first one will be 50 percent of the width of the browser window, the second will be 70 pixels wide, and the third will be allocated whatever space is left over (denoted by the asterisk symbol *). If you set the size of frames using percentages, they will scale accordingly as the browser window is resized. In Figure 3-8, notice the bars that separate the columns; a user can drag these bars to resize the columns. Back in Code Listing 3-8, notice that within the frameset lie the <FRAME> tags. These tags specify which HTML files the browser should display in each column of the frameset.

Click to view at full size.

Figure 3-8. A basic frameset document.

In accordance with the W3C's specifications, Internet Explorer supports a special type of frame called an in-line frame, or IFRAME. Unlike standard frames, which must be created using a frameset document, an IFRAME can be embedded in any standard Web page, just as an IMG or a TABLE can be. Frame number 3 contains an IFRAME that displays the file 1.htm. You can see the IFRAME line in the code for the file 3.htm, shown below.

<HTML>
<BODY BGCOLOR="blue">
This is frame number 3.
<BR>
<IFRAME SRC="1.htm" WIDTH="100">
</BODY>
</HTML>

To learn more about IFRAMEs, consult the SBN Workshop Web site and the CD that accompanies this book. On the CD go to Workshop (References); DHTML, HTML & CSS; HTML References; and then Elements. To get to the online version, visit the MSDN Online Resource page at http://msdn.microsoft.com/resources/schurmandhtml.htm , or open the file named MSDN_OL.htm on the companion CD, and choose HTML Tags and Attributes. No current versions of Netscape Navigator support the IFRAME tag. They will simply ignore it.

Like tables, framesets support embedding, or nesting, where one frame can be contained, or embedded, within another. With this feature, you can create a multitude of layouts. Code Listing 3-9 creates a more complicated frameset document by using nesting as well as a variety of attributes supported by framesets. You can see the results in Figure 3-9.

Code Listing 3-9.

<HTML>
<HEAD>
<TITLE>Listing 3-9</TITLE>
</HEAD>
<FRAMESET ROWS="50,*" FRAMEBORDER="0" FRAMESPACING="0">
  <FRAME SRC="1.htm" NAME="frame1" SCROLLING="no">
  <FRAMESET COLS="20%,80%" FRAMEBORDER="1" FRAMESPACING="1">
    <FRAME SRC="2.htm" NAME="frame2" SCROLLING="yes">
    <FRAME SRC="3.htm" NAME="frame3" SCROLLING="auto">
  </FRAMESET>
</FRAMESET>
</HTML>

Click to view at full size.

Figure 3-9. A more advanced frameset.

NOTE
Another way of creating nested framesets is to point the SRC attribute of a <FRAME> tag to another frameset document. We could have accomplished the same results as we did in Code Listing 3-9 by replacing its inner <FRAMESET> tag with a <FRAME> tag that pointed to an HTML file containing the frameset it replaced. Though each resulting file is simpler than Code Listing 3-9, this approach can be less flexible since changes to the layout of the frameset require edits to multiple files.

Code Listing 3-9 creates a frameset that contains two rows. The first row is 50 pixels tall, and the second takes up the remainder of the screen. The first row consists of a frame that points to 1.htm. The second row contains a separate frameset, which in turn contains two columns of its own.

The FRAMEBORDER and FRAMESPACING attributes control the area between frames. If you want to prevent users from resizing frames, you can set both these attributes to 0, as we did for the outer frameset in Code Listing 3-9. This setting eliminates the space between our top and lower frames—thereby also removing the borders, or bars, between columns. With no bar to drag, users are unable to resize the frames. This can be a handy technique when you want a particular region, such as an advertising banner, to remain a fixed size. Notice in Figure 3-9 that the inner frameset retains its borders and is sizeable because its FRAMEBORDER and FRAMESPACING attributes are not set to 0. Current versions of Netscape Navigator do not provide the level of support for these attributes found in Internet Explorer.

The SCROLLING attribute determines whether and when scroll bars appear in a frame. A no setting prevents scroll bars from ever appearing. You should avoid using this setting unless you are sure that scroll bars will not be needed under any circumstances—for example, your frame will contain no text and only images of known dimensions. Setting SCROLLING to yes means that scroll bars will always be present. An auto setting means that scroll bars will appear only when necessary. The auto setting is especially useful because traditional HTML offers no other way to hide scroll bars until they are needed.

NOTE
Even if you set SCROLLING to auto, browsers set aside space for a scroll bar on the right-hand side of the screen. Without this reserved space, the appearance of the scroll bar would force items on the page to suddenly shift away from the right-hand side of the screen, which might cause an undesirable change in the look of the page.

The NAME attribute, which we used in Code Listing 3-9, allows us to name the frames. Assigning names provides a way for the contents of one frame to address another frame, as the following section explains.

Addressing Across Frames

The ability to address the contents of a frame from any other frame opens up a range of possibilities. Suppose you want to create a navigational toolbar. To make such a feature work, an anchor tag in the navigational frame must be able to address other frames in that frameset. Code Listing 3-10 creates a frameset with a simple navigation bar; Internet Explorer displays the frameset and the bar in Figure 3-10.

Code Listing 3-10.

<HTML>
<HEAD>
<TITLE>Listing 3-10</TITLE>
</HEAD>
<FRAMESET COLS="25%,75%" FRAMEBORDER="1" FRAMESPACING="1">
  <FRAME SRC="nav.htm" NAME="NavFrame" SCROLLING="yes">
  <FRAME SRC="1.htm" NAME="ContentFrame" SCROLLING="auto">
</FRAMESET>
</HTML>

Click to view at full size.

Figure 3-10. A frameset with a navigation bar.

The frameset in Code Listing 3-10 introduces a new HTML file named nav.htm, which contains this series of links:

<HTML>
<BODY>
<A HREF="1.htm" TARGET="ContentFrame">Go to Frame 1</A><BR>
<A HREF="2.htm" TARGET="ContentFrame">Go to Frame 2</A><BR>
<A HREF="3.htm" TARGET="ContentFrame">Go to Frame 3</A><BR>
</BODY>
</HTML>

Notice that each anchor tag contains a TARGET attribute. This attribute's setting tells the anchor which frame in the frameset should change when the anchor is clicked. In this case, when a user clicks one of the links, the contents of the frame named ContentFrame will change to 1.htm, 2.htm, or 3.htm.

You can set the TARGET attribute to a variety of special values (sometimes known as magic values), shown in the following list. (You must include the underscore before each value, and the text must be lowercase.)

_blank | The named document is loaded in a blank, new window.
_self | The named document is loaded into the window that contains the link.
_parent | The named document is loaded into the parent of the window that contains the link. The parent of a frame is the document containing the frameset that called the frame.
_top | Any current frameset is discarded, and the named document is loaded into the full Internet Explorer frame.

For instance, if you want to use a link to exit your current frameset, you can use the setting _top, as shown in the following line of code:

<A HREF="1.htm" TARGET="_top">Exit Frameset</A><BR>

The file 1.htm would then fill the Internet Explorer window, replacing your frameset.

If you set the value of the TARGET to a name that does not exist in the current frameset (such as someotherframe, in our example), the browser will launch a new window that will have that name. All future links with that TARGET will change the contents of this new window.

NOTE
For those who are familiar with scripting, several techniques are available for addressing frames other than the frame that contains a script. The top frame in a frameset is addressed with top, while the parent of the current frame uses parent. The top and parent keywords can be used in conjunction with the name of a frame to gain access to its contents. For example, a script in NavFrame could address an object named myObject in ContentFrame with the code top.ContentFrame.myObject. (If you are not familiar with scripting, don't worry; Part 2 covers this topic in depth.)

Special Considerations

When you are designing Web pages with frames, you might want to keep a few special considerations in mind:

  • For each new frame in a document, Internet Explorer must download a new HTML file. This typically means a new connection with the server, which will slow down the load time of the overall page.

  • Most browsers do not allow you to add a particular frame in a frameset to your Bookmarks or Favorites list but can reference only the frameset as a whole. Users who have added to their Favorites list a location in a frames-based site might be frustrated to discover that this Favorites item returns them to the first page in the frameset.

  • Because many older browsers do not support frames (though they are supported in versions 3 and later of both Internet Explorer and Netscape Navigator), you might want to consider using a <NOFRAMES> tag in your Web pages. Browsers that do not support frames will simply display any text you place between a <NOFRAMES> and </NOFRAMES> tag pair. This text can include anything from a pointer to a nonframes version of your site to a gentle suggestion that the user upgrade to a more recent browser.

  • All links leading to locations outside your site should have a TARGET attribute set to _top. Otherwise, users can find themselves trapped inside your frameset.

Working with frames can be a challenge. When used with care, however, frames can dramatically improve the navigability and style of your Web site.

In the next chapter, we will take a look at forms, through which a user can communicate information to the server; character entities, which allow for the display of characters that are not on the keyboard; and a variety of other useful HTML elements.


Chapter 4 -- Forms, Useful HTML Tags, and Character Entities

 Chapter 4

Forms, Useful HTML Tags, and Character Entities

This chapter describes a number of HTML features that were not covered in previous chapters. First we'll take a look at forms, which enable you to gather information from the users of your Web site. Next we'll examine a variety of specialty tags that can give extra functionality to your Web pages. Finally we'll explore character entities, which allow a developer to specify characters that are not easily accessible via the keyboard.


Forms

Forms allow interaction between a user and a server. The general concept is that the server displays a form to the user via a Web page, requesting any manner of information, such as name, address, phone number, age, and so on. The user then fills out the form and resubmits it to the server. A form can contain a variety of elements, ranging from text entry fields to check boxes and drop-down lists.

Let's take a look at a basic form in Code Listing 4-1, which is displayed in Figure 4-1, and break it down.

Code Listing 4-1.

<HTML>
<HEAD>
<TITLE>Listing 4-1</TITLE>
</HEAD>
<BODY>
<H1>This page contains a form.</H1>
<FORM NAME="F1" ACTION="http://ms.com/asp/prc.asp" METHOD="get">
<B>A text field follows.</B>
<INPUT TYPE="Text" NAME="txtFld" VALUE="A text field" SIZE="25">
<BR><INPUT TYPE="submit">
</FORM>
</BODY>
</HTML>

The Form Tag

The FORM element defines the extent of the form. All of the interactive parts of a form (text fields, select boxes, and so on) should be placed between the opening and closing <FORM> tags. The <FORM> tag supports a number of attributes.

Click to view at full size.

Figure 4-1. A basic form.

The <FORM> tag's NAME attribute gives the form a name. This makes it easier to access the data on the form and is especially useful when you have multiple forms on a page. The ACTION attribute specifies the URL to which the form should deliver its information when a user clicks the Submit button. In Code Listing 4-1, the form will be processed by a file named prc.asp that resides in the asp directory on the Web site ms.com. This site does not actually exist, and thus the form will generate an error when submitted. The type of file specified in the ACTION attribute depends on the type of server being run. Common Gateway Interface (CGI) applications are a common way of processing forms on most Web servers. Microsoft Internet Information Server (IIS) supports Active Server Pages (ASPs), an easy and powerful method of processing forms. Because of the highly server-dependent nature of server-side forms processing, this book will not go into the specifics of writing CGI programs or ASPs (although most of the information provided in the chapters on scripting can be applied to ASPs).

The METHOD attribute specifies how the form should be submitted to the server. There are two standard options: get and post. Get causes the form to act somewhat like an anchor tag. When submitted, the form will try to navigate to a location specified by the following, in the order shown:

  • the URL specified in the ACTION attribute

  • a question mark

  • the contents of the form expressed in name=value pairs

This is simpler than it sounds. For example, if a form has an ACTION of http://www .ms.com/asp/prc.asp and has a text field with the NAME of UserFirstName in which a user has entered the text John, the form will try to link to the location

http://www.ms.com/asp/prc.asp?UserFirstName=John

The file prc.asp on the server will then take the text after the question mark (known as a query string) and process it as the contents of a form. The entire address (including the question mark and any name=value pairs) will be visible in the address bar of the user's browser. Some special characters might appear a bit strange in the address. For example, if you include an equal sign as part of a value, it appears as %3D. If the equal sign were transmitted as itself, it could be confused by the server as the equal sign in a name=value pair.

NOTE
Code Listing 4-1 will return an error message if you click the Submit button. To be processed, forms require a properly configured server that expects form submissions. There is no such server for the forms in this chapter. However, even though the forms in this chapter will return errors if submitted, it is still instructive to do so since it allows you to see the URL requested by the form upon submission.

The post value for the METHOD attribute allows an unlimited amount of data to be sent to the server. If you do this sort of form submission, you will not see the form's information in the address bar. Post is most useful with larger or more complex forms and with those in which you are trying to implement some level of security.

Which METHOD Should You Use?

Your choice of METHOD should be made based on several factors. First, although forms-processing software on most servers can handle both get and post submissions, some are restricted to one or the other. In these cases, your decision is made for you. The primary difference between the two methods is that get includes the form information as part of the URL in the address bar. This can be both an advantage and a disadvantage. A disadvantage is that many people find the form information ugly and distracting. Also, you might want to hide the form information from a user for security reasons. An advantage is that users can bookmark the results of the form submission because the bookmark is saved with the entire URL, including form contents. In addition, this information can give advanced users another method for navigating your site by keying in their own name=value pairs on the address line. If you need to submit a significant quantity of information, post is probably the better choice because get can transfer only a limited amount of information. This limit is typically around 1000 characters, though it varies.

The Input Tag

The form in Code Listing 4-1 contains two <INPUT> tags, one that displays as a text entry field and another that displays a Submit button. As you'll see, the <INPUT> tag is very flexible and allows you to include different types of input ranging from check boxes to text entries in a form. Code Listing 4-2 illustrates all the various TYPE attributes of the <INPUT> tag. Figure 4-2 shows how that code displays on the screen.

Code Listing 4-2.

<HTML>
<HEAD>
<TITLE>Listing 4-2</TITLE>
</HEAD>
<BODY>
<FORM NAME="F1" ACTION="http://ms.com/asp/prc.asp" METHOD="get">
<INPUT NAME="t1" TYPE="text" VALUE="This is a text input"><BR>
<INPUT NAME="p1" TYPE="password" VALUE="A password input"><BR>
<INPUT NAME="c1" TYPE="check box" VALUE="Check box 1">
This text is next to check box 1.<BR>
<INPUT NAME="c2" TYPE="check box" VALUE="Check box 2">
This text is next to check box 2.<BR>
<INPUT NAME="r1" TYPE="radio" VALUE="first radio ">
This text is next to the first radio button.<BR>
<INPUT NAME="r1" TYPE="radio" VALUE="second radio">
This text is next to the second radio button.<BR>
<INPUT NAME="b1" TYPE="button" VALUE="Just a button"><BR>
<INPUT NAME="f1" TYPE="file" VALUE="This is a file input."><BR>
<INPUT NAME="h1" TYPE="hidden" VALUE="A hidden input"><BR>
<INPUT NAME="rst" TYPE="reset" VALUE="A reset button"><BR>
<INPUT NAME="sbt" TYPE="submit" VALUE="A submit button"><BR>
<INPUT NAME="i1" TYPE="image" VALUE="An Image" SRC="a.gif"><BR>
</FORM>
</BODY>
</HTML>

Click to view at full size.

Figure 4-2. The various types of INPUT elements.

Every <INPUT> tag should contain a TYPE and a NAME attribute, and most will include a VALUE attribute. The TYPE attribute specifies what type of input will be requested from the user, such as a text box, check box, or radio button. The NAME attribute and the final contents of the VALUE attribute are sent to the server for processing when the form is submitted. Such information is known as a name=value pair. Other attributes vary with the input tag TYPEs, as you will see in the following paragraphs.

Setting a value of text for the TYPE attribute displays a single-line text entry field. This kind of field is useful for collecting such information as names and addresses from users. Input tags of TYPE text support a SIZE attribute, which specifies the visible width of the field. Additionally, you can use the MAXLENGTH attribute to establish the maximum number of characters allowed in the field and set the READONLY attribute to true to disable the field for user input. (Current versions of Netscape Navigator do not support the READONLY attribute.) The following tag would generate a text entry field 30 characters wide that would scroll as the user entered up to 100 characters.

<INPUT NAME="t1" TYPE="text" SIZE="30" MAXLENGTH="100">

Any initial value specified in the VALUE attribute will display by default in the text entry field. If a user replaces this information (as is likely), the contents of the VALUE attribute will be updated so that when the form is submitted it will contain the information specified by the user.

Setting a value of password for the TYPE attribute displays a single-line text entry field in which asterisks appear instead of the actual characters typed by the user. As you would expect, this setting is useful for obtaining information from the user that you don't want displayed in a readable format on the client side, such as passwords. Input tags of TYPE password support all the same attributes as those of TYPE text and behave identically, except in terms of character display.

Setting a value of check box for the TYPE attribute displays a standard check box. Adding the CHECKED attribute (just add the word CHECKED to the tag) results in a check box that is already checked. An input tag of TYPE check box is submitted with the form only if the check box is checked.

Setting a value of radio for the TYPE attribute displays a standard radio button. Adding the CHECKED attribute displays a radio button that is already selected. Typically, radio buttons are used to select one and only one choice from a number of alternatives. For this scenario, you should create multiple input tags of TYPE radio and give them the same NAME attribute, as seen in Code Listing 4-2. This combines the individual radio TYPEs into a single radio group and allows only one item in the group to be selected at a time. If a user selects one item, and then another, the first item will automatically deselect. The NAME of the radio group is submitted to the server with the value of the selected item. If no items are selected, no information from the radio group is submitted.

Setting a value of button for the TYPE attribute displays a button. Whatever is specified in the VALUE attribute is used as the text of the button. Buttons can perform actions through script. Scripting will be covered in Part 2.

Setting a value of file for the TYPE attribute displays a text entry field and a Browse... button. This TYPE of input tag allows users to find and specify files on their machines. (This TYPE of input tag is not supported in Microsoft Internet Explorer version 3 unless the user has installed the file upload add-on.) When the Browse... button is clicked, a standard Browse dialog box appears (the standard dialog box for the user's operating system) that lets the user graphically navigate the computer's file system. For security reasons, you cannot set a value for any input of TYPE browse.

Setting a value of hidden for the TYPE attribute results in an input that is not displayed. Hidden input tags are used to keep track of information that the user does not need to see. These TYPEs of input tags can be particularly beneficial when used in combination with scripting.

Setting a value of reset for the TYPE attribute displays a Reset button. A Reset button will return the form to its default state, meaning all the input fields will return to the conditions they were in when the form was first downloaded. If you specify a VALUE attribute for this tag, the text will be used for the text of the button instead of the default text, Reset. A name=value pair is not submitted for Reset buttons since they perform an action on the client side rather than carry data. The same is true for input tags of TYPEs submit and image, discussed next.

Setting a value of submit for the TYPE attribute displays a Submit button. When this button is clicked, the form is submitted. As with the Reset button, if you specify a VALUE attribute, that text will be used for the text on the Submit button instead of the default, Submit Query.

An alternative to using a Submit button is to use the value image for the TYPE attribute. This value displays an image that acts just like the Submit button, in that when it is clicked, the form is submitted. An <INPUT> tag that uses the image TYPE attribute supports two additional attributes: SRC and ALIGN. SRC defines the location of the image that should be displayed, and ALIGN specifies where the image should display relative to the text around it, just like the <IMG> tag.

The Text Area Tag

In addition to the <INPUT> tag, forms support a number of other interactive elements. The <TEXTAREA> tag allows for multi-line text input. Code Listing 4-3 demonstrates the <TEXTAREA> tag. Figure 4-3 displays the results.

Code Listing 4-3.

<HTML>
<HEAD>
<TITLE>Listing 4-3</TITLE>
</HEAD>
<BODY>
<FORM NAME="F1" ACTION="http://ms.com/asp/prc.asp" METHOD="GET">
<TEXTAREA NAME="TA1" COLS="40" ROWS="4" WRAP="soft">
  This text is inside TEXTAREA 1. Note how lines of code are
  automatically wrapped and how line breaks in the code cause breaks.
</TEXTAREA>
<BR>
<TEXTAREA NAME="TA2" COLS="40" ROWS="4" WRAP="off">
  This text is inside TEXTAREA 2. Note how lines of code are
  not automatically wrapped and how line breaks in the code cause breaks.
</TEXTAREA>
<BR><INPUT TYPE="submit">
</FORM>
</BODY>
</HTML>

Click to view at full size.

Figure 4-3. Use of the TEXTAREA element.

<TEXTAREA> is similar to an <INPUT> of TYPE text in that it allows for text entry in a form. However, the <TEXTAREA> tag allows multiple lines of text to be entered. When the form is submitted, any text inside a TEXTAREA element is submitted as the value of the element. The text between the opening and closing tags of the element is displayed as the default text, as visible in Figure 4-3. This text and any changes made by the user are sent to the server for processing when the form is submitted.

You can set the size of the element with the COLS and ROWS attributes. COLS specifies the width of the TEXTAREA element in characters, while ROWS specifies the number of text lines a user can enter without needing to scroll. The WRAP attribute determines how the text wraps. In Internet Explorer 5, text is normally wrapped by default, while it is not normally wrapped in Netscape Navigator. A value of off turns off text wrapping; a value of soft or hard turns it on. The soft and hard values differ only in how they submit information to the server. Soft does not submit line breaks to the server, and hard submits line breaks as seen in the browser window. Internet Explorer also supports the READONLY attribute, which makes the text in the element non-editable, and the DISABLED attribute, which takes the READONLY attribute one step further by also graying out the element.

Select and Option Tags

The <SELECT> and <OPTION> tags allow for the creation of list boxes. Code Listing 4-4 demonstrates three list boxes. The results are displayed in Figure 4-4.

Code Listing 4-4.

<HTML>
<HEAD>
<TITLE>Listing 4-4</TITLE>
</HEAD>
<BODY>
<FORM NAME="F1" ACTION="http://ms.com/asp/prc.asp" METHOD="get">
Select one item:
<SELECT NAME="sbt1">
  <OPTION VALUE="option1">Text of option 1
  <OPTION VALUE="option2" SELECTED>Text of option 2
  <OPTION VALUE="option3">Text of option 3
  <OPTION VALUE="option4">Text of option 4
  <OPTION VALUE="option5">Text of option 5
</SELECT>
<HR>
Select one item:
<SELECT NAME="sbt2" SIZE="3">
  <OPTION VALUE="option1">Text of option 1
  <OPTION VALUE="option2" SELECTED>Text of option 2
  <OPTION VALUE="option3">Text of option 3
  <OPTION VALUE="option4">Text of option 4
  <OPTION VALUE="option5">Text of option 5
</SELECT>
<HR>
Select multiple items:
<SELECT NAME="sbt3" MULTIPLE ALIGN="top">
  <OPTION VALUE="option1">Text of option 1
  <OPTION VALUE="option2" SELECTED>Text of option 2
  <OPTION VALUE="option3">Text of option 3
  <OPTION VALUE="option4">Text of option 4
  <OPTION VALUE="option5">Text of option 5
</SELECT>
<BR><INPUT TYPE="submit">
</FORM>
</BODY>
</HTML>

Click to view at full size.

Figure 4-4. Creating drop-down lists.

The <SELECT> tag supports two kinds of lists: standard (usually called drop-down) and multi-select. These are both shown in Figure 4-4. The extent of the list is defined by the SELECT element. Inside the SELECT element reside OPTION elements, each representing an item in the list. A closing </OPTION> tag is not necessary. The SELECT element supports a number of attributes. If you include the MULTIPLE attribute, the list box will allow multiple selections. With multi-select lists, users can press and hold the Ctrl key while they click each item they want; or they can click an item, press and hold the Shift key, and click a different item to select a range.

The SIZE attribute specifies the default number of rows that display. For standard lists, the default SIZE is 1, meaning only one line displays unless the user clicks the drop-down button, which then displays a scrollable list of items. If you set a standard list SIZE greater than 1, a scrolling list of options displays, from which one option can be selected. For multi-select lists, the default SIZE is 4. Changing this SIZE changes the number of items displayed.

Each OPTION element should have a VALUE attribute. When the form is submitted, the NAME of the SELECT element is included with the VALUEs of the selected items in the list as the name=value pairs. If multiple OPTIONS have been selected, each selection is submitted as part of its own name=value pair. If you include the SELECTED attribute in an OPTION element, that OPTION element becomes the default selected item in the list. Descriptive text follows each of the OPTION elements. This text is what the user sees in the drop-down list.

All of the elements above can be used in Internet Explorer, either inside a form or on their own. Current versions of Netscape Navigator, however, require that these elements live inside a FORM element; otherwise, they are not displayed as described above, but rather as simple text. For example, the descriptive text following the <OPTION> tags in a SELECT list will simply display as in-line text (like in a normal paragraph), rather than in a drop-down list.

Forms are tremendously practical. Many of their most powerful features, however, require knowledge of scripting. Scripting is covered in Part 2.


Other Useful HTML Tags

There are many HTML tags in addition to those already discussed. The tags described in this section are the remainder of those that we have found most useful. Appendix E contains a list of all HTML tags supported in Internet Explorer 5 with a brief description of each. A complete reference to these tags can be found on the SBN Workshop Web site and on the CD that accompanies this book. On the CD go to Workshop (References); DHTML, HTML & CSS; HTML References; and then Elements. To get to the online version, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm , or open the file named MSDN_OL.htm on the companion CD, and choose HTML Tags and Attributes.

Comment Tags

It is often useful to make notes, or comments, inside your HTML files that will not actually display on the screen. Such comments can help to (1) describe what various parts of a file are supposed to do; (2) explain why a piece of code was written in a certain way; (3) include information in a file that you do not want to be displayed, such as copyright information and author names; or (4) disable parts of a file. There are two forms of HTML comment tags, which are illustrated in Code Listing 4-5 and displayed in Figure 4-5.

Code Listing 4-5.

<HTML>
<!--
Author:   Eric Schurman
Purpose:  Demonstrate comments
Location: Chapter 4
-->
<HEAD>
<TITLE>Listing 4-5</TITLE>
</HEAD>
<BODY>

<!--This is an example of a single line comment -->
<B>This is a normal block of HTML. The rest of the HTML
on this page does not display because it is disabled, or
<I>"commented out,"</I> through the use of comments.</B>

<!--This multi-line comment disables ("comments out") some HTML.
This <B>line of HTML</B> is commented out in both browsers.
-->

<COMMENT>This type of comment is part of HTML 4.0.</COMMENT>

<COMMENT>This one comments out some more HTML.
This is <B>yet more commented out HTML</B>. This type of
comment tag does not work in Netscape Navigator 3 and 4.
</COMMENT>

</BODY>
</HTML>

Click to view at full size.

Figure 4-5. Use of the different comment tags.

The first type of comment tag used has <!-- as the opening tag and --> as the closing tag. All text between these two tags is treated as a comment and not displayed on screen. This type of comment tag is by far the most common. The first such comment in Code Listing 4-5 is found at the beginning of the file and contains information about the file itself. Notice that the opening and closing tags are not on the same line. In this instance, all the intermediate lines are treated as comments and are not displayed. The second comment demonstrates a single-line comment, in which the opening and closing tags are on the same line. The last comment of this type surrounds some normal HTML code, which therefore is not displayed. Placing comment tags so that they cause code not to display is known as commenting out the code. This is a powerful debugging technique: if part of your file is not acting as expected, you can pinpoint the problem areas by selectively commenting out parts of the code until you find the source of the issue.

The second type of comment tag opens with <COMMENT> and closes with </COMMENT>. This comment tag is supported by Internet Explorer and Mosaic but not by any current version of Netscape Navigator. In Internet Explorer, this type of comment tag will function identically to the first type, but it will have no effect in Netscape Navigator; therefore, the text between the <COMMENT> tags will be visible to the Netscape Navigator user. It is possible to take advantage of this difference in browser behavior. If you want to display a message to Netscape Navigator users only, simply place it inside a COMMENT element. Internet Explorer will not display it, while Netscape Navigator will.

Meta Tags

In the previous code sample, we used comment tags to provide context at the beginning of our document. Providing context is one of many roles played by the metainformation <META> tag. This tag can also be used to furnish a number of services not directly related to the content of the page. Following is a list of some of the tasks you can accomplish with <META> tags, along with the corresponding code:

  • Force a page to refresh after a set number of seconds (5 in the sample below).

    <META HTTP-EQUIV="REFRESH" CONTENT="5">

  • Load a non-English character set for the document (Japanese in the sample below). The specified character set will display only if it is both supported and installed on the client's computer.

    • <META HTTP-EQUIV="Content-Type" CONTENT="text/html;
    CHARSET=Windows-51932">

  • Force a page to not be cached (stored locally). Some browsers do not support this feature.

    • <META NAME="Pragma" CONTENT="No-Cache">

  • Indicate that the document's contents expired at a point in the past, which forces the page not to be read from the local cache:

    <META HTTP-EQUIV="Expires" CONTENT="Thursday, 18-Jan 96 16:26:30 GMT">

  • Redirect the user to a different page after a set period of time:

    <META HTTP-EQUIV="refresh" CONTENT="5;URL=http://www.microsoft.com">

  • Include keywords, a description, a document type, and a revisit interval that will be used by many Web search engines:

    <META NAME="keywords" VALUE="DHTML, CSS, ActiveX, HTML, JScript">
<META NAME="description" VALUE="Description of DHTML.">
<META NAME="type" CONTENT="User Manual">
<META NAME="revisit-after" CONTENT="10 days">

<META> tags almost always should be placed at the very top of the HEAD element in a file. You should be aware that many search engines will ignore your <META> tags if you repeat a word too many times. Using synonyms or describing a wider variety of items in a keyword <META> tag is typically a much better policy.

Many people will use <META> tags with custom NAME attributes to track information about a page. For example, <META> tags with NAME attributes of ISBN, Author, and Title could be used to track information about a book. Some search engines are capable of searching on such custom <META> tags.

FieldSet and Legend Tags

The <FIELDSET> and <LEGEND> tags are useful for grouping types of information together. They are especially handy in forms. The <FIELDSET> tag draws a line around its contents. The <LEGEND> tag (which, if used, must be the first element within a FIELDSET element) names the FIELDSET. Code Listing 4-6 provides examples of different types of FIELDSETs. The results are displayed in Figure 4-6.

Code Listing 4-6.

<HTML>
<HEAD>
<TITLE>Listing 4-6</TITLE>
</HEAD>
<BODY>
<FIELDSET>
This fieldset has no LEGEND.
</FIELDSET>
This text comes after Fieldset number 1.
This text comes after Fieldset number 1.
This text comes after Fieldset number 1.
<FIELDSET TITLE="A Fieldset">
<LEGEND>Fieldset 2</LEGEND>
This content is inside Fieldset 2.
</FIELDSET>
This text comes after Fieldset number 2.
This text comes after Fieldset number 2.
This text comes after Fieldset number 2.
<FIELDSET ALIGN="right" STYLE="width:140">
<LEGEND>Fieldset 3</LEGEND>
This content is inside Fieldset 3.
</FIELDSET>
This text comes after Fieldset number 3.
This text comes after Fieldset number 3.
This text comes after Fieldset number 3.
<FIELDSET>
<LEGEND ALIGN="center">Fieldset 4</LEGEND>
This content is inside Fieldset 4.
</FIELDSET>
This text comes after Fieldset number 4.
This text comes after Fieldset number 4.
This text comes after Fieldset number 4.
</BODY>
</HTML>

Most of the code in the sample should be fairly self-explanatory. Note, however, that the third FIELDSET has both an ALIGN attribute and a STYLE attribute. The ALIGN attribute causes the FIELDSET to display at a particular location relative to the text around it, like the IMG element, which is covered in Chapter 2. Normally, however, the FIELDSET takes up the entire width of the screen, so there is no room for it to appear to one side or the other of text. In the sample, we used the STYLE attribute to set a FIELDSET width of 140 pixels; thus allowing room for text. The STYLE attribute will be covered in depth in Part 3.

The FIELDSET tag is part of the HTML 4.0 specification and is not supported in any current version of Netscape Navigator. In Navigator (and in any browser that does not support FIELDSET elements), content inside FIELDSET or LEGEND elements is displayed as standard text.

Figure 4-6. Several examples of FIELDSETs, with and without LEGENDs.

Image Maps

An image map is a graphic that contains hyperlinks to a number of different locations. Where the user clicks on the image map determines the hyperlink that is activated. Image maps consist of two major components, an IMG element and a MAP element. The IMG element (see Chapter 2) is a standard <IMG> tag with the addition of a USEMAP attribute, which references the MAP element that should be used with the image with the MAPs NAME attribute. If the specified MAP element is defined in the same file as the USEMAP attribute, a pound symbol (#) should precede the name of the map, as shown in Code Listing 4-7 and displayed in Figure 4-7.

Code Listing 4-7.

<HTML>
<HEAD>
<TITLE>Listing 4-7</TITLE>
</HEAD>
<BODY>
<IMG SRC="nav.gif" WIDTH="300" HEIGHT="200" USEMAP="#NavMap">
<MAP NAME="NavMap">
<AREA SHAPE="rect" COORDS="0,0,50,100" HREF="http://www.microsoft.com">
<AREA SHAPE="circ" COORDS="100,150,20" HREF="http://www.w3c.org">
<AREA SHAPE="poly" COORDS="200,50,250,50,250,100,200,150,150,100"
HREF="http://mspress.microsoft.com">
</MAP>
<BR>
<A HREF="http://www.microsoft.com">Microsoft</A>
<A HREF="http://www.w3c.org">W3C</A>
<A HREF="http://mspress.microsoft.com">Microsoft Press</A>
</BODY>
</HTML>

Click to view at full size.

Figure 4-7. Users can click on the image to navigate.

The MAP element contains any number of AREA elements, each of which specifies a shape, a location on the image map, and a hyperlink, using the SHAPE, COORDS, and HREF attributes, respectively.

The SHAPE attribute supports rectangles with the rect and rectangle values, circles with circ and circle, and polygons with poly and polygon. Each of these SHAPES uses the COORDS attribute slightly differently. For circles, the first two numbers in the COORDS attribute are the x and y coordinates at the center of the circle, relative to the top left of the graphic. The third number is the radius of the circle. For rectangles, the first two numbers are the x and y coordinates for the upper left corner of the rectangle, while the second two numbers are the coordinates for the lower right corner. Finally, for polygons, each pair of numbers represents the coordinates of another point in the polygon. By using many points in a polygon, you can create detailed shapes.

Always include alternate navigation routes when using image maps. Code Listing 4-7 includes standard text hyperlinks for this task. This practice ensures that users who have turned off images in their browsers or have browsers that cannot display images can still follow your links. This is especially important for blind users.

NOTE
The blue border around the image can be disabled by setting the IMG's BORDER attribute to 0.

Span and Div Tags

The <SPAN> and <DIV> tags are known as container tags. They are useful for separating a block of text from its surroundings without imparting any formatting of their own. These tags are frequently used with Cascading Style Sheets (CSS), which is covered in detail in Part 3.

SPAN is an in-line element, meaning that it can be embedded in text and flow with the paragraph without causing a line break. Some other common in-line elements are B (boldface), U (underline), and I (italic). Each of these elements flows in a paragraph without causing a line break. In contrast, DIV is a block element, which does not flow in a paragraph. Instead, the DIV element is treated as a separate block of text and becomes its own paragraph. Some other common block elements are P (paragraph), HR (horizontal rule), TABLE, and list elements such as UL (unordered list), OL (ordered list), and LI (list item). Code Listing 4-8 demonstrates some basic uses of styles with the SPAN and DIV tags. Note that the two similar lines of code produce quite different results in Figure 4-8.

Code Listing 4-8.

<HTML>
<HEAD>
<TITLE>Listing 4-8</TITLE>
</HEAD>
<BODY>
Here is <SPAN STYLE="font:bold 14pt">some text</SPAN> in a SPAN.
<HR>
Here is <DIV STYLE="font:bold 14pt">some text</DIV> in a DIV.
</BODY>
</HTML>

Click to view at full size.

Figure 4-8. Basic styles on SPAN and DIV elements.

The XMP (Example) Tag

The <XMP> tag can be extremely useful. This tag acts like the <PRE> tag (covered in Chapter 2), except that in addition to formatting the displayed text with the same spacing as the HTML text, it causes the underlying HTML code to display on the screen. Code Listing 4-9 illustrates the <XMP> tag, and Figure 4-9 displays the results.

Code Listing 4-9.

<HTML>
<HEAD>
<TITLE>Listing 4-9</TITLE>
</HEAD>
<BODY>

<P>
This paragraph contains <B>bold</B>,
<I>italic</I>, and <U>underline</U> tags.
</P>

<XMP>
<P>
This paragraph contains <B>bold</B>,
<I>italic</I>, and <U>underline</U> tags.
</P>
</XMP>

</BODY>
</HTML>

Click to view at full size.

Figure 4-9. The XMP tag exposes the underlying code.

Notice that Internet Explorer displays the first paragraph as we would expect: elements surrounded by formatting tags (<B>, <I>, and <U>) are formatted appropriately. The second paragraph is enclosed in an XMP element and is displayed quite differently. Rather than display the formatted text, the browser renders the code in raw form, including the HTML tags. This technique is extremely useful when constructing pages that contain examples of HTML code.

The World Wide Web Consortium (W3C) has officially deprecated this tag and recommends that it no longer be used. However, the <XMP> tag is supported in Internet Explorer 5 (as it was in versions 4 and 3) for the purpose of maintaining backward compatibility. There is no new substitute tag that does exactly what the <XMP> tag does. However, a similar effect can be accomplished using the <PRE> tag with character entities, discussed next.


Character Entities

A character entity is simply a code that represents a character. Every character that can be displayed on the screen has a corresponding character entity. Character entities are useful when you want to display a character that would normally present display or entry difficulties. For example, suppose you want to display a less-than symbol (<) in the browser. This symbol is normally used to signify the beginning of an HTML tag and, if simply keyed in as text, could confuse the browser. Instead, you can use a character entity to represent the symbol and avoid potential problems. This concept is demonstrated in Code Listing 4-10 and displayed in Figure 4-10.

Code Listing 4-10.

<HTML>
<HEAD>
<TITLE>Listing 4-10</TITLE>
</HEAD>
<BODY>

Display in bold that X is less than Y: <B> X&lt;Y </B>.
This paragraph uses a character entity.

<HR>

Display in bold that X is less than Y: <B> X<Y </B>.
This paragraph does not use a character entity.
</BODY>
</HTML>

Click to view at full size.

Figure 4-10. Character entities display as their corresponding characters.

The first sample uses the character entity for the less-than symbol (&lt;) and, as a result, everything displays as expected. The second sample uses the less-than character itself. In this instance, everything between the less-than character and the end of the closing boldface tag is treated as though it is inside an HTML tag and is not displayed. Additionally, the closing boldface tag is no longer parsed properly; thus, the rest of the text on the page displays in boldface.

A character entity is composed of three parts. The first is the ampersand symbol (&). This lets the browser know that a character entity begins here. Next comes either a number, prefaced with a number sign (#), or a name that identifies the specific entity. All entities have numerical identifiers, while some frequently used entities have been given names and are known as named entities. The less-than entity shown previously is a good example. It can be identified with either #60 or lt. The last part of the character entity is the semicolon (;). This signifies the end of the entity to the browser. A list of many common entities can be found in Appendix D. Table 4-1, on the following page, lists some of the most commonly used character entities.

NOTE
The numerical values for character entities are derived from the Unicode version 2.0 (more specifically, the ISO standard ISO10646) character set, a table of tens of thousands of characters from all over the world.

In the next chapter, we will investigate the Document Object Model. This tool for content developers goes beyond traditional HTML and allows an unprecedented level of control in Web page construction.

Table 4-1.

Displays As | Numerical Identifier | Named Entity | Description | Notes
 | &#09; |  | Horizontal tab |
 | &#13; |  | Carriage return |
 | &#32; |  | Space |
! | &#33; |  | Exclamation mark |
" | &#34; | &quot; | Quotation mark | Can be useful in script
/ | &#47; |  | Solidus (slash) |
< | &#60; | &lt; | Less than | Prevents the browser from interpreting < as the beginning of a tag
> | &#62; | &gt; | Greater than |
\ | &#92; |  | Reverse solidus (backslash) |
... | &#133; |  | Ellipsis |
™ | &#153; |  | Trademark |
 | &#160; | &nbsp; | Nonbreaking space | Useful for "nudging"(inserting a small amount of space) or to separate two words between which you do not want a line break
© | &#169; | &copy; | Copyright |
® | &#174; | &reg; | Registered trademark |
± | &#177; | &plusmn; | Plus or minus |
² | &#178; | &sup2; | Superscript two |
³ | &#179; | &sup3; | Superscript three |
¹ | &#185; | &sup1; | Superscript one |
¼ | &#188; | &frac14; | Fraction one-fourth |
½ | &#189; | &frac12; | Fraction one-half |
¾ | &#190; | &frac34; | Fraction three-fourths |
æ | &#230; | &aelig; | Lowercase ae ligature |


Chapter 5 -- The Dynamic HTML Object Model

 Chapter 5

The Dynamic HTML Object Model

Traditionally, HTML documents were static pages. Just as the pages in this book do not change once they are printed, a Web page did not change once it was displayed. If new information needed to be presented to the user, a new page had to be created. Some developers sidestepped this limitation by displaying information in ActiveX controls or in Java applets that allowed dynamically changing content, but these approaches were usually limited and required proprietary components or controls that a user had to download.

In 1996, Microsoft and a company named SoftQuad presented a proposal defining a Document Object Model to the World Wide Web Consortium (W3C). The proposal outlined a way in which a browser could represent an HTML page and provide a standard mechanism for accessing parts of the document. On October 1, 1998, the W3C issued the Document Object Model (DOM) Level 1 Specification. The Microsoft Internet Explorer Dynamic HTML Object Model is Microsoft's current implementation of the proposed standards.

This chapter takes a look at the underlying principles of the Dynamic HTML Object Model, followed by an overview of the components it comprises. In upcoming chapters, we will investigate how this Dynamic Object Model can be manipulated through the use of script, resulting in dynamic and interactive Web pages. Netscape Navigator supports an Object Model with many of the same components as the Object Model in Internet Explorer. However, the Navigator Object Model supports a more limited list of features and fewer options for content manipulation than does Internet Explorer.


Underlying Principles of the Dynamic HTML Object Model

The Dynamic HTML Object Model was created with several goals in mind:

  • To define a hierarchical structure representing all parts of a Web document

  • To allow the modification of that structure through the addition and removal of content

  • To provide a way of monitoring and manipulating the characteristics of content on the page

  • To provide information about how the items on a page interact with the user and each other

The Internet Explorer Dynamic HTML Object Model allows a developer to programmatically control everything on the page and to change virtually anything at any time. It allows reporting of keyboard and mouse events and even lets a developer dynamically change the HTML that makes up the page. Any such changes are immediately visible to the user. Incorporation of the Dynamic HTML Object Model was one of the most sweeping changes to Internet Explorer version 4.

Because the Dynamic HTML Object Model allows an unprecedented amount of control over the page, it encourages the developer to include far more interactivity between a user and a Web page than was previously possible. Here are a few examples of effects that can be easily created using the Dynamic HTML Object Model with script:

  • An index expands or collapses when the user clicks an entry.

  • When the user passes the mouse pointer over an image of a button in a default state, the image can be exchanged for that of a button in a selected state, making the button appear to pop up.

  • The user can drag text or images around on a page.

  • Items can move around on a page without user interaction and end up positioned exactly where the designer wants them.

  • Text appears when the user positions the mouse pointer over an image.

  • The formatting of text, graphics, and tables can be changed on the fly.

  • Parts of the page are dynamically created or destroyed based on user input.


Basic Components of the Dynamic HTML Object Model

Now that you've seen what can be done with the Dynamic HTML Object Model, let's take a look at its components. (In the discussion that follows—and throughout the book—you'll notice that we often use the shorter term "Object Model" or "Dynamic Object Model" to refer to the Dynamic HTML Object Model.)

Objects

As you've seen in previous chapters, an HTML page contains elements, which are usually defined by opening and closing tags surrounding specific content. Some elements are contained within others; a table row (TR) element is contained in a table element, for example.

Every element on a page is represented in the Dynamic Object Model as an object, the basic unit of the Object Model. Examples of such elements include an image, a span of text, the body region of an HTML document, or even an ActiveX control—in short, anything described in the text of an HTML file.

The Object Model is a hierarchical representation of all these objects. At the highest level of the hierarchy is the window object, which represents the frame or browser window in which the current page is displayed. All the rest of the objects on a particular page are subobjects of that page's window object. In other words, all HTML elements are represented as lower in the Object Model hierarchy than the window object.

If an element on the page is contained within another element (such as a cell within a table), it is represented in the Object Model as a subobject of the object that contains it. A subobject is also called a child of the object that contains it, while the containing object is known as a parent. Thus, a table is parent to any child TR elements inside it, and the window object is parent to all other objects on a page.

The most common way to refer to an object in Internet Explorer is by using the ID attribute to give it a name. For instance, the code <IMG ID="MyImage"> assigns the name MyImage to an image object. Alternatively, the NAME attribute can be used: for example, <FORM NAME="F1">. NAME is commonly used in forms.

Once an object has been named, it can be referred to easily through script, as you will see in Chapter 7. In almost all cases, an object's name should be unique; using the same name for multiple objects can cause a variety of problems.

An object can contain properties, events, methods, and collections. The Object Model exposes all these aspects of an object, making them accessible and controllable. The next few sections provide a general overview of properties, events, methods, and collections; a full description can be found on the SBN Workshop Web site and on the CD that accompanies this book. On the CD go to Workshop (References); DHTML, HTML & CSS; and HTML References. To get to the online version, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm, or open the file named MSDN_OL.htm on the companion CD, and choose DHTML Properties, Events, Methods, and Collections.

Properties

In traditional HTML, you can modify an element by setting its attributes. The attributes contain information describing that element. Just as an HTML element is represented in the Dynamic Object Model by an object, an element's attributes are represented by properties of that object. For instance, here is a simple image tag:

<IMG SRC="oldpic.gif" WIDTH="10" ID="MyImage">

This <IMG> tag has three HTML attributes: SRC, WIDTH, and ID. On the Web page, this code creates an image element with three attributes; the ID attribute names the image, while SRC and WIDTH specify the source graphic and the width of the image, respectively. This resulting element is represented in the Object Model by an object, and the three attributes are represented as the src, width, and id properties of that object. In the Object Model, these properties are accessible—that is, they can be changed or read by script code. How this is accomplished is covered in Chapter 7.

In addition to the src, width, and id properties, the Object Model makes many other properties available for an image object such as the one in the previous example. For instance, even though our sample HTML does not include a HEIGHT attribute, the height property of the image object is accessible through the Object Model. In fact, the IMG object has nearly 50 properties, which describe everything from the image's alignment to the date the source file was created.

Events

Internet Explorer tracks just about everything that happens on a page. For instance, if a user clicks a picture, the browser knows that the mouse button was clicked and that it was clicked while the mouse pointer was positioned on that particular image. An action or occurrence on the page, such as a mouse click, is referred to as an event. When an event occurs on the page, the item that receives the event notifies the Dynamic Object Model that the event has taken place. This is known as firing the event. An event is trapped or handled if script is present that responds to the firing of that event. Such script is known as an event handler.

Browsers support many types of events, with special emphasis on mouse, keyboard, and focus events. Here are a few examples:

onmousedown event | Fired when the user presses the mouse button
onmouseover event | Fired when the user positions the mouse pointer over an object
onmouseout event | Fired when the user moves the mouse pointer outside the boundaries of an object
onkeypress event | Fired when the user presses a key
onfocus event | Fired when an object receives the focus

NOTE
An item has the focus when it is selected. Only one item can have the focus at any particular time. For instance, when you work with a large online form that contains many text entry fields, you can type in only one field at a time. The field you can type in is the one that currently has the focus. Clicking a different field sets the focus to that field; pressing the Tab key switches the focus to different items on a page.

The onclick event is a special event that can be fired by either the mouse or the keyboard. This event is designed to make a page more accessible to a user who doesn't have a mouse. Here are some of the cases that fire this event:

  • The user clicks an object with the mouse.

  • An object has the focus, and the user presses the Enter key.

  • A check box or an option button (also known as a radio button) has the focus, and the user presses the Spacebar.

  • The user presses an object's keyboard access key (often known as a hot key). The hot key is set with the accessKey property.

Browsers also support a variety of other, more specialized events, including:

onhelp event | Fired when the user presses the F1 key
onload event | Fired when an object finishes loading
onresize event | Fired when the window is resized
onscroll event | Fired when the window is scrolled

Many additional events exist and are described on the SBN Workshop Web site and on the CD that accompanies this book. Netscape Navigator supports most of the same events as Internet Explorer, but it does not support trapping them on as wide a variety of objects.

EVENT BUBBLING

The Internet Explorer Object Model supports a capability referred to as event bubbling. When an object fires an event, it also notifies its parent object that the event has occurred. The parent object then notifies its parent object. The event continues to travel, or "bubble," up the hierarchy until it either reaches the top or the bubbling action is explicitly canceled. A real-world equivalent might be asking your boss for a substantial raise and then having the request travel up the corporate hierarchy until it reaches someone who has the authority to deal with the request. You can find more details about event bubbling in Chapter 7.

Methods

Methods describe the actions an object can take. For instance, the window object has a method named open, which directs the window to open a new browser window.

Some methods are fairly generic, whereas others are quite specific. For instance, almost all objects support the focus method, which simply gives the item the focus (and results in the object firing the onfocus event). Other methods are particular to a single object. For example, an ActiveX control used to show movies might support a method named Run that starts the movie. Another example is the reload method, supported only by the location object, which causes the current page to be reloaded in the browser.

Collections

Collections are, in general, the least used part of the Dynamic Object Model. Collections are lists of items that are associated with a particular object. Just as a museum has a collection of paintings or a library has a collection of books, the Object Model also maintains collections. For instance, the document object supports a collection named images, a list of all the image objects that appear in the document, in the order in which they appear in code.

In this chapter, we have investigated the basic concepts behind the Dynamic HTML Object Model. In Part 2, we will cover scripting, which lets us apply the concepts outlined in this chapter. Scripting is a powerful, flexible, and easy way to manipulate the components of the Dynamic Object Model as well as to accomplish many traditional programming tasks.


Chapter 6 -- Introduction to Scripting

 Chapter 6

Introduction to Scripting

One of the most important and exciting innovations to traditional Web browsers was the addition of scripting. Through scripts, Web designers can add a level of interactivity and sophistication to their Web pages that is typically found only in advanced applications. Scripts are blocks of program code that are "embedded" in Web pages and interpreted at run time. This simply means that the text file containing the HTML also contains some additional text that issues commands to the browser.

In the same way that Microsoft Internet Explorer 5 interprets HTML to determine what to display on the screen, it also interprets any script it encounters to determine what actions to take. This script must be written in one of a set of specific programming languages that the browser understands. For example, the Web page shown in Code Listing 6-1 contains some simple script that causes an image to change when the user clicks it.

Code Listing 6-1.

<HTML>
<HEAD>
<TITLE>Listing 6-1</TITLE>
</HEAD>
<BODY>
<IMG ID="MyImage" SRC="oldpic.gif" onclick="MyImage.src=`newpic.gif'">
</BODY>
</HTML>

This chapter offers an overview of scripting and how it relates to the Dynamic HTML Object Model described in Chapter 5. We'll examine some basic examples of scripting, such as the one that appears in Code Listing 6-1. The remaining chapters in Part 2 provide full coverage of scripting techniques.

NOTE
Netscape Navigator (through at least version 4) does not support as full a Dynamic HTML Object Model as Internet Explorer. For example, it does not support the onclick event with images. As a result, Code Listing 6-1 does not change the image when clicked in Navigator, though it also does not cause any errors. The file IENSSWAP.htm in the crosplat folder on the companion CD demonstrates a complete cross browser image swapping solution. The solution is somewhat code intensive, however, and so is not appropriate for an introductory discussion of scripting. More cross browser development tricks are presented throughout this book and particularly in Chapter 23.


Scripting Options in Internet Explorer

Internet Explorer natively supports two scripting languages, Microsoft Visual Basic Scripting Edition (VBScript) and a Microsoft version of JavaScript, called JScript.

Internet Explorer is also a scripting host—that is, support for other scripting languages, such as Perl, can be added. This hosting capability lets developers use scripting languages with which they are already comfortable directly inside Internet Explorer, without having to learn another language. It also allows them to use scripts previously written in one of these other languages in Internet Explorer without having to rewrite the scripts in another language. This is especially handy on the server side and when using Internet Explorer to develop tools that will be used on a limited number of machines that all have the requisite scripting engine installed. This book does not discuss script language hosting in depth, but the SBN Workshop Web site and the CD that accompanies this book are good resources on this subject.

NOTE
Perl is a mature scripting language that is popular on UNIX systems. It is supported as both a stand-alone and Web server scripting system on a wide variety of platforms, including all 32-bit versions of Windows. No major browser currently ships with built-in support on the client side for Perl. More information about Perl can be found at www.activestate.com and www.perl.com.

VBScript

VBScript is a relative of Microsoft's popular Visual Basic programming language. Internet Explorer is the only browser that currently supports VBScript, although the language is supported on the Web server side by Microsoft Internet Information Server (IIS) with Active Server Pages (ASP). VBScript is attractive to programmers who are already familiar with Visual Basic because many of the constructs and the syntax in both languages are the same (or at least quite similar), which makes VBScript easy to learn.

In Internet Explorer 5, VBScript is not included with a minimal installation of the browser, although it is automatically downloaded when needed from the Internet. Additionally, as mentioned earlier, VBScript is not currently supported in any browser other than Internet Explorer. Because of this, the scripting samples in this book use JScript to enable them to function in other browsers.

JavaScript and JScript

Although its name might imply that JavaScript is a subset of Java, it is not. JavaScript is a completely separate language from Java that was developed by a different company. (Java was developed by Sun Microsystems; JavaScript was originated by Netscape Communications.) Despite the differences, however, JavaScript does share some constructs and syntax with its namesake. Java developers will recognize hints of the Java language in JavaScript, and although JavaScript is not quite as forgiving as VBScript, even novices will find it relatively straightforward to learn and use. (In fact, experienced script writers often prefer JavaScript for its more rigid syntax compared to VBScript.)

JScript is the version of JavaScript that is part of Internet Explorer. In most respects, JScript is exactly the same as JavaScript. JavaScript and JScript evolved over time, resulting in some incompatibilities between browsers and browser versions. The European Computer Manufacturer's Association produced a standard (ECMAScript or ECMA-262), encompassing the core features of JavaScript and JScript. Internet Explorer versions 4 and later and Netscape Navigator versions 4.06 and later support ECMA-262, although each support some extra functionality. We will be using JScript for the scripting examples in this book. Like the other scripting languages listed above, JScript/JavaScript is supported on many Web servers.

NOTE
On the SBN Workshop Web site and on the CD that accompanies this book is a useful JScript reference that will be mentioned frequently in upcoming chapters. For another online reference, check out the JScript section of the Microsoft Web site at msdn.microsoft.com/scripting.


The Capabilities of Scripting

Scripting offers great features as well as some inherent limitations. On the upside, scripts (in their simple form) are easy to learn and use, they run on the client side, they can be developed quickly, and they are powerful. On the downside, scripts have some security-based limits, are not as fast as traditional compiled languages (like C++) for computationally intense operations, and they can sometimes be complex.

EASE OF USE Basic scripting is extremely easy to learn and use. Scripts bring much of the power of programming to the nonprogrammer in the form of simple blocks of code that respond to user actions (event-driven code). For instance, it is easy to make a simple chunk of code run when the user clicks a specific image. With scripting languages, you can also avoid many of the more time-consuming and difficult tasks in traditional programming, such as memory management and garbage collection. In addition, you don't need special tools or a development environment to get started with scripts. The advantages of scripting are available to anyone who has a browser and a simple text editor.

CLIENT-SIDE PROCESSING Another significant advantage is that scripts run on the client side. Once a page has been downloaded, all its scripts run on the user's browser rather than on a server that might be halfway around the world. (This advantage is especially important when combined with other features such as form validation, multimedia, and the Dynamic HTML Object Model, as you will see later.) This is quite different from the old method of sending the user a new Web page every time the page should change content or appearance. Anyone who views your Web pages with a script-capable browser can use your scripts without installing any extra software—and potentially without even knowing that scripts are being used. To the viewer, scripts are seamless and invisible.

RAPID DEVELOPMENT Scripts are interpreted languages—that is, it is not necessary to compile the code before it is run, as it is for C++ and other traditional programming languages. As a developer, you can create a script in an HTML file and execute it immediately in a browser. If you need to make a change to the script, you can simply edit the HTML file, reload it in the browser, and instantly view the effect of your change.

POWER Despite their simplicity, scripts can be very powerful. While novices enjoy the ease of learning, advanced programmers like the power, flexibility, and advanced features of scripts. These features include object orientation, the ability to create objects at run time, support for a variety of data types, and control over virtually everything in the browser. Scripts allow Web page creators to add sophisticated logic to their pages, making the pages both active and interactive.

SECURITY ISSUES The power of scripting in the browser is limited in certain areas. Other than certain very specific cases (for example, cookies, Default Behaviors, and the FileSystem ActiveX control), Internet Explorer does not allow scripts to read or write files on the user's hard disk. This prohibition is intended to prevent rogue Web programmers from damaging end users' hard disks or stealing their data. For those developing tools that require more extensive hard drive access, the Windows Scripting Host allows you to write script for Windows outside a browser, and the FileSystem ActiveX control (which must be specifically loaded and approved by the user) allows you to write script for the file system and hard drive from within Web pages.

PERFORMANCE Because VBScript and JScript were designed for ease of use and simplicity, they do not offer the same level of performance that many traditional compiled languages offer. For example, it is possible to write a mathematically intensive encryption program in JScript, but it would probably be prohibitively slow. However, this is not normally much of a restriction because most tasks you would want to perform in a browser do not require high computational performance.

COMPLEXITY A common misconception is that because basic scripting is easy, all scripting is easy. In fact, VBScript and JScript are sophisticated languages, and mastering them requires a thorough understanding of programming concepts. Because of this complexity, beginners are often a bit overwhelmed when first exposed to advanced scripts. Fortunately, many users will never need advanced scripting techniques because so much is possible with simple event-driven code.

Overall, you will find that scripts are invaluable resources in creating sophisticated, interactive Web pages that take full advantage of the power of the browser. Let's take a look at how scripts work.


Scripts in HTML

Every element in HTML has a tag, and scripts are no different. In most cases, for the browser to recognize a script and execute it properly, the script must exist inside a set of script tags. Script tags generally look like this:

<SCRIPT LANGUAGE="JavaScript">
<!--
[The actual script commands]
//-->
</SCRIPT>

The first line is the opening script tag. Just as you need an opening tag for a block of boldface text (<B>) or a title (<TITLE>), you need one for a script (<SCRIPT>). The first line also specifies a language, identifying the language being used within that particular script block. (Although JavaScript and JScript can be used interchangeably with Internet Explorer for the LANGUAGE attribute, we specify JavaScript instead of JScript because some other browsers do not recognize the JScript script tag.) As you might guess, you can mix and match script blocks of different languages, such as VBScript and JScript, on the same page. The different blocks can even refer to one another. However, this will incur a slight loading and performance penalty.

The <!-- and --> symbols are the opening and closing comment tags in HTML. These let you set aside text that the browser should not render on the screen. It is a good idea to include comment tags like this around scripts because older browsers that do not recognize scripts will ignore everything inside these comment tags. They are not necessary when producing pages for more recent browsers. Two forward slashes (//) act to comment out a line in JScript, thus, in this case, they comment out the --> tag. This will prevent errors in Netscape Navigator, which tries to execute these characters as script when they reside in a script element. The last line in the sample code is the closing script tag, </SCRIPT>. It serves to define the end of the script, just as the </TITLE> tag serves to end the title of a page.

In addition to enclosing script within opening and closing script tags, you can also point a script tag to an external file containing script. This is accomplished through the SRC attribute, similar to how an <IMG> tag refers to a graphic to display. For example, if you had an external file named jsLibrary.js, you could reference it as follows:

<SCRIPT LANGUAGE="JavaScript" SRC="jsLibrary.js"></SCRIPT>

Using a reference to an external script has several advantages. If you have some script that you would like to access from many different pages on your site, you can simply place the script in an external file that is referenced by every such page. By using one source, you avoid the problem of accidentally using different versions of your script in different files. Additionally, once downloaded, the script file is cached (stored locally on the user's machine), which means that the script does not need to be downloaded separately as part of every Web page. This can reduce downloading time substantially. This technique works in Netscape Navigator 3 and later and Internet Explorer 3.02 and later.

Finally, scripts that handle events that occur to specific elements on the page can be incorporated into elements themselves. Such scripts are called embedded event handlers, and will be discussed later in this chapter.


Scripting a Web Page

As you learned in Chapter 5, almost every element in Internet Explorer and many in Netscape Navigator—from an image to the background color of the page itself—is available (exposed) as an object. This availability means that all the objects can be accessed through scripts. We will use this capability to demonstrate some basic scripting techniques. This concept will be covered in detail in Chapter 7.

Code Listing 6-2 shows an HTML page with an image tag. We will use this as a base to which we will add script.

Code Listing 6-2.

<HTML>
<HEAD>
<TITLE>Listing 6-2</TITLE>
</HEAD>
<BODY>
<IMG ID="MyImage" SRC="oldpic.gif">
</BODY>
</HTML>

The code in Code Listing 6-2 is standard HTML. The <IMG> tag specifies an image. The ID attribute used with this tag gives the image a name—in this case, MyImage—so that we can easily reference it later through the Dynamic Object Model. The last part of the image tag uses the SRC attribute to specify the source for that image: Internet Explorer will display the image named oldpic.gif.

Now we create some script that has an effect on the image we set up:

<SCRIPT LANGUAGE="JavaScript">
<!--
MyImage.src="newpic.gif";
//-->
</SCRIPT>

The core of this script is the line MyImage.src-"newpic.gif". In the original HTML (Code Listing 6-2), we specified the SRC attribute for the MyImage image tag. In the Dynamic Object Model, this sets the src property of the MyImage object. To refer to an object's property, you specify the object's name and use a period to separate it from the property name: MyImage.src, for example. (To find out more about naming conventions, see the sidebar "Notation and Naming" in Chapter 7). When it is run, the script will access the MyImage object in the Dynamic Object Model and change the value of its src property from oldpic.gif to newpic.gif. Internet Explorer then changes the displayed image to newpic.gif.

Basic Event Handlers

The preceding code looks pretty good. We have an HTML page containing an image. We have a script that changes the displayed image to another image. We now need to combine them and let Internet Explorer know when to call the script that changes the image.

Most scripts are activated when some sort of event happens. For example, loading the HTML page is an event. Moving the mouse is another event. Whenever an event happens on a page, Internet Explorer knows about it. Scripts that handle events are referred to, appropriately, as event handlers. Code Listing 63 adds an event handler that runs the script when the MyImage object is clicked. This type of event handler is supported only in Internet Explorer. Embedded event handlers, discussed next, are more widely supported.

Code Listing 6-3.

<HTML>
<HEAD>
<TITLE>Listing 6-3</TITLE>
<SCRIPT LANGUAGE="JavaScript" FOR="MyImage" EVENT="onclick">
<!--
MyImage.src="newpic.gif"
//-->
</SCRIPT>
</HEAD>
<BODY>
<IMG ID="MyImage" SRC="oldpic.gif">
</BODY>
</HTML>

The event handler appears inside the <SCRIPT> tag in Code Listing 6-3. It consists of two parts: the FOR attribute lets the script know that we are concerned with the object named MyImage; the EVENT attribute determines which event will be handled—in this case, the event is onclick (a mouse click). Thus, this script block is activated only when the user clicks the image referred to by the MyImage object. To see this script in action, open lst6-3.htm in the chap06 folder on the companion CD. When Internet Explorer displays the page, click the image in the upper left and watch it change. To refresh the page and return the image to its original state for further testing, click the Refresh button on the Internet Explorer toolbar or press its keyboard equivalent, the F5 key.

NOTE
Notice that we inserted the script in the header region of the HTML in Code Listing 6-3. Scripts can be inserted anywhere on a page, depending on the script writer's preference and the needs of the page. When possible, it is a good idea to keep all scripts in the same place on an HTML page to make them easier to find and to aid in the debugging process. Keeping a script in the header region also ensures that the script is loaded before the rest of the page, which can be helpful when you are debugging.

Embedded Event Handlers

Embedded event handlers are often easier to create than the one shown in Code Listing 6-3. To embed an event handler, we can insert the code to handle the event inside the target tag itself, as shown in Code Listing 6-4.

Code Listing 6-4.

<HTML>
<HEAD>
<TITLE>Listing 6-4</TITLE>
</HEAD>
<BODY>
<IMG ID="MyImage" SRC="oldpic.gif" onclick="MyImage.src=`newpic.gif'">
</BODY>
</HTML>

The Web page in Code Listing 6-4 works just like the previously created page; when the user clicks the image, the image changes. But the image tag now contains an event handler that specifies what should be done when the image is clicked and the onclick event occurs. In this case, onclick is set to MyImage.src-'newpic.gif'. Notice that this setting is the same as the contents of the <SCRIPT> block in Code Listing 6-3, except for the quotation marks. In Code Listing 6-4, double quotation marks enclose the entire onclick expression, which describes what should happen when the image is clicked. Within that expression, single quotation marks enclose the filename newpic.gif. The double quotation marks tell Internet Explorer where the event handler begins and ends; if we had used a double quote instead of the first single quote, for instance, we would have ended the onclick expression prematurely. We could also have reversed the usage of the two types of quotation marks and used single quotes to surround the event handling code and double quotes to surround the file name. The important thing is to use the same type of quotation mark to begin and end each part of the code.

Embedded event handlers have a few limitations. Only JavaScript and JScript support them; VBScript does not. They also can make the HTML somewhat hard to read, especially if you use a long string of multiple commands. You can learn more about event handlers in Chapter 7.

Functions

The scripts you've seen so far in this chapter have been tied to a specific event for a specific object on the page (a click on MyImage, for example). To make the script accessible from multiple events occurring on multiple objects, we might create individual copies of the script, one for each image, each with its own event handler. But this technique involves many scripts and a lot of maintenance. Fortunately, there is a better way.

A function is a named block of program code that can be called by its name. Separating a script from a specific event handler and making it a function allows us to access it from multiple events, as shown on the following page.

<SCRIPT LANGUAGE="JavaScript">
<!--
function changeImage(){
  MyImage.src="newpic.gif"
}
//-->
</SCRIPT>

NOTE
Because this book targets modern browsers that understand the <SCRIPT> tag, we will leave out the <!-- and //--> commenting tags for most of the remainder of the book. If your site is intended also for browsers that do not understand script (for example, Netscape Navigator version 1 or some text-only browsers), use commenting tags as appropriate.

Notice that we removed the event handler part of the <SCRIPT> tag (the FOR and EVENT attributes) and changed the internal parts of the script to a function. In this case, the name of the function is changeImage. We can use this name to run the code within the function from elsewhere on the HTML page.

Because functions usually perform an action, it's a good idea to use verbs in their names. Parentheses, which are required, follow the function name. In more advanced functions, you'll see argument names within these parentheses. An argument is simply information that is being passed to the function. The empty parentheses in our sample function indicate that we are not passing any arguments to the function. (For now, don't worry if you are a little unclear on passing arguments; we will cover function arguments in detail in Chapter 9.)

Also notice the curly braces—{ and }—after the function name and at the end of the script. These braces, which are often used in JScript to describe conceptually distinct blocks of code, define the beginning and end of the block of code that comprises the function.

We now need an event to activate this function. The following HTML contains an embedded event handler:

<BODY>
<IMG ID="MyImage" SRC="oldpic.gif" onclick="changeImage()">
</BODY>

The onclick handler we added to the <IMG> tag has been set to changeImage( ). This tells Internet Explorer to run the function changeImage when the user clicks this graphic. In other words, the onclick event handler calls the changeImage function. Now let's see what all this looks like. Code Listing 6-5 puts the HTML back together with the script code. When you run this script (chap06\lst6-5.htm on the companion CD), it will act like the script in Code Listing 6-3 and Code Listing 6-4. Now, however, the script is a function and can be used by anything that calls that function. This is demonstrated by the heading tag.

Code Listing 6-5.

<HTML>
<HEAD>
<TITLE>Listing 6-5</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function changeImage(){
 MyImage.src="newpic.gif"
}
</SCRIPT>
</HEAD>
<BODY>
<IMG ID="MyImage" SRC="oldpic.gif" onclick="changeImage()">
<H1 onclick="changeImage()">Click here or on the image.</H1>
</BODY>
</HTML>

This code shows multiple elements calling one function. The changeImage function is called by both MyImage and the heading. With this script, clicking either the image or the text causes the image to change. (Don't forget that you can refresh the page by pressing F5 or by clicking the Refresh button.)

At this point, you should have a basic understanding of how scripts can add power and flexibility to your Web pages. Now that we have covered the basics, we will examine some of these topics in more depth. In the next chapter, we will investigate how scripting can interact with the Dynamic Object Model. After that, we will explore the types of data supported by JScript and JavaScript and how they can be manipulated. We will then cover how to control scripts using functions, conditional expressions, and loops. The last scripting chapter will cover some advanced scripting capabilities, like error handling.


Chapter 7 -- Object-Oriented Scripting

 Chapter 7

Object-Oriented Scripting

In Chapter 5, we introduced the concept of an Object Model, which is used by browsers to internally represent a Web page. In Chapter 6, we provided an overview of scripting. A key feature of the Object Model is its ability to be controlled through scripting. This chapter details how scripts can manipulate and interact with the Object Model.


Looking at Objects

In the Microsoft Internet Explorer Object Model, each HTML element on the page is represented by an object in conjunction with other objects that are not explicitly declared in the HTML file, such as the window object and the document object. The following list provides a sample of some of the objects you'll encounter:

A | BUTTON | DIV | document
event | history | IMG | location
navigator | screen | selection | SPAN
style | TABLE | userProfile | window

In Appendix C, you'll find a complete list of all the standard objects that are a part of the Internet Explorer Object Model. Full descriptions of all the objects can be found on the SBN Workshop Web site and on the CD that accompanies this book. On the CD see Workshop (References) DHTML, HTML & CSS; DHTML References; Objects. To get to the online version, visit the MSDN Online Resource page at http://msdn.microsoft.com/resources/schurmandhtml.htm , or open the file named MSDN_OL.htm on the companion CD, and choose DHTML Objects. The Netscape Navigator Object Model is a little different from that of Internet Explorer. We'll cover many of the differences throughout the rest of this chapter.

NOTE
You can see from the preceding list of objects that the capitalization of object names varies. Objects shown in all uppercase letters (such as IMG and SPAN) are standard HTML elements. Objects shown in mixed case or lowercase letters are not HTML elements but are additional features of the overall Object Model—the screen object, for example, contains information about the end user's display, and the navigator object provides information about the version and type of browser being used.


Reading and Changing Properties

A property describes a characteristic of an object. For example, an IMG object has width and height properties, which define the image's dimensions, and the src property, which specifies the graphics source file that the IMG object should display. In Internet Explorer, virtually all properties can be both read and manipulated through script. Code Listing 7-1 provides an example of how this works. Figure 7-1 shows how this code is initially displayed; Figure 7-2 shows what happens after the user clicks OK.

NOTE
As of this writing, the Object Model found in Netscape Navigator is not as full featured as that in Internet Explorer. Because of this, Navigator (at least through version 4) will not display many of the samples in this chapter as expected, including Code Listing 7-1. Although Navigator does not let you access a particular image with the techniques shown in this listing, you can read (but not change) properties of an image by accessing it through the document object's image collection. Thus, instead of using Img1.width, as in Code Listing 7-1, you could use document.images[0].width. Chapter 24 demonstrates more techniques for accomplishing cross browser scripting.

Code Listing 7-1.

<HTML>
<HEAD>
<TITLE>Listing 7-1</TITLE>
</HEAD>
<BODY>
<IMG ID="Img1" SRC="circle.gif">
<SCRIPT LANGUAGE="JavaScript">
alert("Img1 has width "+Img1.width+" and height "+Img1.height)
Img1.height=150
Img1.width=30
alert("Now it has width "+Img1.width+" and height "+Img1.height)
</SCRIPT>
</BODY>
</HTML>

Click to view at full size.

Figure 7-1. The dialog box indicates the width and the height of the image.

Click to view at full size.

Figure 7-2. When the image changes, the dialog box indicates the new property values.

In this example, our HTML page contains an image object named Img1. The block of script first produces an Alert dialog box that displays the existing width and height of the image. To get these values, the script refers to the image's properties using dot notation, the naming scheme used in the Object Model. (See the sidebar "Notation and Naming" in "Reading and Changing Properties" below for more information.) Although the width and height properties can apply to many different objects, the expressions Img1.width and Img1.height in Code Listing 7-1 refer to the width and height properties of the Img1 object only. The plus signs that accompany these expressions in Code Listing 7-1 are not part of the naming convention. They simply serve to join, or concatenate, the pieces of text, enclosed in quotes, with the values of the named properties, resulting in the sentence displayed in the Alert dialog box. Next the script changes the values of Img1's width and height properties by setting them to new values. A dialog box displays the new width and height of the image, as shown in Figure 7-2.

In Internet Explorer, all HTML attributes have equivalent properties in the Object Model: the WIDTH attribute and the width property, the SIZE attribute and the size property, to name only two. But the Object Model contains many additional properties that are not available as attributes. This list provides a few examples of properties used in the Object Model:

background | href
borderColor | innerHTML
cellPadding | pixelHeight
color | src
Display | tabIndex
fileCreatedDate | visibility
fontFamily | zIndex

Appendix C contains a complete list of all the standard properties that Internet Explorer supports. Full descriptions of all the properties, including the objects they apply to, can be found on the SBN Workshop Web site and on the CD that accompanies this book. On the CD see Workshop (References); DHTML, HTML & CSS; DHTML References; Properties. To get to the online version, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm, or open the file named MSDN_OL.htm on the companion CD, and choose DHTML Properties.

Although all properties are readable through script, not all of them are writable—that is, not all properties can be changed on the fly through script, as the width and height properties were changed in Code Listing 7-1. For instance, the IMG object's fileSize property describes the size of an image's source file in bytes. Because this property is based on a physical value that the browser cannot control (because it is not an image-editing program), changing it through script would not be meaningful. Additionally, different browsers are able to change different properties. Internet Explorer versions 4 and later are able to change the way many aspects of the elements are displayed, such as the width of an image already on the page. Internet Explorer versions 3 and earlier and all currently released versions of Netscape Navigator are unable to change most such properties.

NOTE
Internet Explorer 5 allows you to monitor changes to an object's properties. This is accomplished through the new onpropertychange event and the propertyName property of the event object. Events and event handlers are covered in more depth later in this chapter.

Notation and Naming

Dot notation gives you a clear, convenient way to refer to objects and their components when you write scripts. In this naming convention, the name of an object and the name of its child object, property, event, method, or collection are separated by a dot (a period). For example, the expression window.document.linkColor refers to the linkColor property of the document object, which is a child object of the window object.

It is not always necessary to provide the full name when using dot notation. For instance, if your script code is acting on items that are in the same window, you can usually omit the name of the window object. Thus, document.linkColor refers to the linkColor property of the document in the current window.

Names are case sensitive in the Object Model when using JScript. To have items in the Object Model behave properly, your code must refer to them using the proper case—WINDOW.DOCUMENT.LINKCOLOR is not the same as window.document.linkColor. For instance, if we had tried to set the height property of Img1 in Code Listing 7-1 by writing Img1.HEIGHT, the height of the image would not have changed because the height property must be lowercased. As a general rule, you should lowercase the names of properties, methods, and collections if the names are single words (such as src or height) and use mixed case if the names consist of multiple words (such as fileSize or fileModifiedDate).

Creating Expando Properties

Internet Explorer 4 and later support a special class of properties referred to as expando properties. These are user-created properties that do not map to the intrinsic properties of an object. For example, the following line of script creates a new property of Img1; the new property is named AssociatedText, and its value is set to the words This book covers JScript.:

Img1.AssociatedText="This book covers JScript."

You could use such a new property to associate information with a graphic; for instance, if Img1 were a picture of a book, this expando property could be a description of the book. Expando properties can be read or changed at any time. It is useful to follow a different naming convention when creating expando properties. For example, we capitalized the first letter of each word in the property. This makes it easier to keep track of which properties are expando and which are built-in.


Trapping Events

As you saw in Chapters 5 and 6, objects in the Object Model fire specific events when certain actions occur. For instance, a button INPUT on a form fires an onclick event when it is clicked, and the window object fires an onerror event when an error occurs. Appendix C provides a complete list of all the events supported in Internet Explorer. Full descriptions of all the events can be found on the SBN Workshop Web site and on the CD that accompanies this book. On the CD see Workshop (References); DHTML, HTML & CSS; DHTML References; Events. To get to the online version, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm, or open the file named MSDN_OL.htm on the companion CD, and choose DHTML Events.

A number of the more common events are supported by both Netscape Navigator and Internet Explorer. These include onclick, ondblclick, onmousedown, onmouseup, onmousemove, onmouseover, onkeypress, onkeydown, onkeyup, and onresize. Netscape Navigator is fairly particular about exactly which events are supported on different objects. For example, HTML elements that support onclick in Navigator 4 are document, A, and INPUT (types button, check box, radio, reset, and submit). Additionally, many elements that support one event do not support others. For example, a button INPUT in a form supports onclick, but not onmouseover. Internet Explorer supports most events (especially the common ones like mouse events) on almost all objects.

An event is not very useful unless script that responds to the event is available. Such script is known as an event handler. Code Listing 7-2 demonstrates a standard method of assigning script to handle a particular event, also known as trapping the event.

Code Listing 7-2.

<HTML>
<HEAD>
<TITLE>Listing 7-2</TITLE>
</HEAD>
<BODY>
<FORM onload="alert(`BODY loaded.')">
<INPUT TYPE="button"
  VALUE="Click Me"
  onclick="alert(`You clicked the button.')"
  onmouseover="alert(`You moused over the button.')">
</FORM>
</BODY>
</HTML>

One of the easiest ways to trap an event is to use an embedded (also known as inline) event handler (as you saw in Code Listing 6-4). In Code Listing 7-2, an event handler is embedded in both the <BODY> and <INPUT> tags. Inline event handlers are the most widely supported type of event handler, with at least partial support going back several years. Both Netscape Navigator and Internet Explorer will display an alert message when the body loads and when the button is clicked, but Navigator will not display an alert when the mouse passes over the button for reasons detailed above. (If you find that the first dialog box interferes with clicking the button, dismiss that dialog box by pressing the enter key rather than by clicking OK.)

Code Listing 7-3 demonstrates the three common ways of trapping events, not all of which are supported in all browsers. Figures 7-3 through 7-7 illustrate how the code behaves in Internet Explorer. Figure 7-8 shows how a click on the body is handled by Netscape Navigator.

Code Listing 7-3.

<HTML>
<HEAD>
<TITLE>Listing 7-3</TITLE>

<SCRIPT LANGUAGE="JavaScript">
// If using NS 4+ capture click events (unnecessary in Internet Explorer)
if (window.Event){
  document.captureEvents(Event.CLICK)
  document.onclick=EventInfoNS      // Bind the EventInfoNS function
}
else{document.onclick=EventInfoIE}  // Bind EventInfoIE to a click for IE

function EventInfoIE(){
  // Display what fired the event, its name, the event type, and where
  e=window.event
  alert("The "+e.srcElement.tagName+" element called "+e.srcElement.id+
    " fired the "+e.type+" event. This occurred at screenX="+
    e.screenX+" and screenY="+e.screenY+".")
}

function EventInfoNS(e){
  // Display what event happened where
  alert("A "+e.type+" occurred at screenX="+e.screenX+" and screenY="+
    e.screenY+".")
}
</SCRIPT>

<SCRIPT FOR="Span1" EVENT="onmouseover" LANGUAGE="JScript">
  // This code runs when the mouse travels over the SPAN
  Span1.innerHTML="You moused over this."
</SCRIPT>
</HEAD>
<BODY ID="theBody">
<IMG ID="Img1" SRC="circle.gif">
<SPAN ID="Span1" onmouseout="this.innerHTML=`You left it.'">
  This is the first state.
</SPAN>
</BODY>
</HTML>

Click to view at full size.

Figure 7-3. Initially, the Internet Explorer window looks like this; but as you move the mouse and click it, different events occur.

Click to view at full size.

Figure 7-4. When you move the mouse over the text in the SPAN element, the onmouseover event is fired and the text changes.

Click to view at full size.

Figure 7-5. When you move the mouse away from the text, the onmouseout event is fired and the text changes again.

Click to view at full size.

Figure 7-6. In Internet Explorer, an Alert dialog box indicates that the IMG object was clicked.

Click to view at full size.

Figure 7-7. In Internet Explorer, a different Alert dialog box is displayed when the text is clicked.

Click to view at full size.

Figure 7-8. The contents of the Netscape Navigator window after the body of the document is clicked.

NOTE
Code Listing 7-3 above uses JScript comments (the lines beginning with two forward slashes). Comments are a useful and highly recommended way of noting the purpose of different parts of your code.

As you can see, an embedded event handler is used in the <SPAN> tag:

<SPAN ID="theSpan" onmouseout="this.innerHTML=`You left it.'">

This code specifies the onmouseout event, and then it binds the script "this.innerHTML='You left it.'" to that event. The keyword this references the current object—in this case, theSpan. Thus, whenever the mouse leaves the SPAN element, that object's innerHTML property is set to the text You left it. Because this property specifies what should appear inside the SPAN element, you will see the new text displayed on the screen. Although Netscape Navigator supports embedded event handlers, it will not actually do anything when the mouse leaves the SPAN element. This is because it does not support onmouseout or onmouseover on SPAN elements, nor does it support changing an element's innerHTML property.

Another way to trap an event is to create a block of script devoted solely to that event, as we did in Code Listing 6-3, and as seen in the first script block in Code Listing 7-3. The script block begins with a standard <SCRIPT> tag and includes a FOR attribute, which specifies the object being tracked, an EVENT attribute, which specifies the event to be handled, and as with all SCRIPT tags, a LANGUAGE attribute:

<SCRIPT FOR="theSpan" EVENT="onmouseover" LANGUAGE="JavaScript">

This block of script runs whenever the object named theSpan experiences an onmouseover event. When you run this code and move your mouse over the text displayed by the SPAN element, the text changes to read You moused over this (as shown in Figure 7-4). This method of trapping events is supported only in Internet Explorer.

You can also trap an event by binding a function to the event. This is supported in both Netscape Navigator and Internet Explorer, though with some differences between the two. To do this, the page must contain a named function. (We introduced functions in Chapter 6, and we will cover them in more depth in Chapter 9.) For example, Code Listing 73 contains two functions named EventInfoNS and EventInfoIE.

In Netscape Navigator, you must first notify the browser that you want to capture click events with the captureEvents method, so we first check whether Navigator is being used, capture the click event, and then bind the EventInfoNS function to the event with the following code.

if (window.Event){
  document.captureEvents(Event.CLICK)
  document.onclick=EventInfoNS
    }

An if statement is used to determine whether the window object has a child object named Event. (You'll find more detail about if statements in Chapter 9.) This will be true only in Netscape Navigator version 4 and later (a similar object in Internet Explorer is named event, with a lowercase "e"). If the window object contains such an object, click events are captured and the EventInfoNS function is bound to the event.

In Internet Explorer, there is no need to state explicitly that we want to capture the event, since almost all events are automatically captured. In fact, because it is not supported, the captureEvents method will cause errors in Internet Explorer. This is why the previous test was performed. The following code causes the EventInfoIE function to be run whenever the onclick event is fired by the document object in Internet Explorer:

document.onclick=EventInfoIE

Note that the syntax for actually binding a function to an event is the same between browsers.

Let's take a deeper look at the EventInfoIE function in Code Listing 7-3, which is used by Internet Explorer. The listing contains the following code, which displays an Alert dialog box containing information about the element that was clicked.

e=window.event
alert("The "+e.srcElement.tagName+" element called "+e.srcElement.id+
  " fired the "+e.type+" event. This occurred at screenX="+
  e.screenX+" and screenY="+e.screenY+".")

In Internet Explorer the window object has a child object named event, which is available when an event is occurring (and only exists for the duration of that event). We first assign this object to a variable named e. This step is not required but makes it easier to refer to the object later in our code and results in code that performs faster than specifying the entire hierarchical object name every time. The event object has a variety of useful properties. For example, its srcElement property specifies the particular object that fired the event. The alert code above uses srcElement to retrieve information about the type of tag that fired the event, the tag's name, and the type of event fired. Other properties of the event object report information such as the position of the mouse on screen (screenX and screenY), the position of the mouse relative to the top left of the browser window (clientX and clientY), and the identity of keys pressed. You can see this function in action by clicking anywhere on the Web page—on the image, on the text, or even on the blank background area. Notice that the Alert dialog box displays the tag name of whatever item is clicked, even though the onclick event is bound only to the document object. This is a result of event bubbling, explained in the next section.

The EventInfoNS function, used by Netscape Navigator, takes a single parameter e used to represent the Event object. Navigator's Event object supports a number of properties, including screenX, screenY, type, pageX, pageY, target, and several others. This function will display an alert of the type of event that occurred and where it occurred on screen. Note that the function is only called when the body itself (not the text or image) is clicked.

Event Movement Through the Object Model

Netscape Navigator and Internet Explorer have very different ways of communicating events through the Object Model. As described in Chapter 5, when an event occurs to an object in Internet Explorer, the event "bubbles up" through the Object Model hierarchy until it either reaches the top or is explicitly cancelled. Because the document object is further up the hierarchy than all visible objects on an HTML page, any click on any object is reported to it. Thus, an onclick event handler on the document object will respond to any click on any object. Event bubbling in this fashion is a standard way of communicating events in many operating systems and development environments.

Netscape Navigator behaves in exactly the opposite fashion: events travel from the top of the object hierarchy to the bottom. At the top, the event is captured as shown in Code Listing 7-3. If you want the event to be processed by some object further down the hierarchy, you can use the routeEvent and handleEvent methods to direct travel of the event. More information about this can be found at developer.netscape.com. An excellent tutorial in the Netscape Navigator Object Model can be found at webreference.com, where you will also find many useful articles, including a comparison between the Object Models in Internet Explorer and Netscape Navigator.

Sometimes you will not want an event to bubble up to the parent of an object in Internet Explorer. For example, we might want the image in Code Listing 7-3 to react to a click differently than does every other element on the page. We could accomplish this by adding the following event handler to the image in Code Listing 7-3:

    onclick="alert(`I react differently.');window.event.cancelBubble=true">

Figure 7-9 shows the new results when the image is clicked.

Click to view at full size.

Figure 7-9. Clicking the image now generates this display rather than the one shown in Figure 7-6.

Now when the image is clicked, its own embedded event handler displays an alert and then sets the cancelBubble property of the event object to true. This prevents the event from bubbling up to parent objects. As a result, the document object does not receive the onclick event when the image is clicked, and the displayEvent function is not executed. The document object can still receive onclick events from the other objects on the page, however, because they have not canceled event bubbling.

Event bubbling can be both a great timesaver and a big pain. Allowing one handler to trap events on several objects can save coding work, but it can sometimes result in confusion when you do not want a particular object's event to have an effect. Appendix A presents some examples of this problem as well as some workarounds.

NOTE
When using event bubbling, it is almost always better to use the document object instead of the window object. This is because many of the events that bubble up to the document object do not go on to the window object.


Calling Methods

You can use script to call one of an object's methods, causing an action to occur. In JScript, a method name is always followed by parentheses, as shown here:

window.open()

This line of script calls the open method of the window object, which causes the browser to open a new window on the screen. Within the parentheses, some methods support arguments, which serve to modify the action taken by the method. For instance, the code window.open( ) opens a new, completely blank window, which is not very useful. Instead, you might want to direct this new window to point to a particular location, have a name, be a certain height, and not have a menu bar. To carry out such instructions, the open method supports a variety of arguments, as you can see in this example:

window.open("http://www.w3.org","W3","width=40,height=95,menubar=no")

The first argument in this script directs the open method to point the new window to the World Wide Web Consortium home page. The second argument gives the new window the name W3. This name can be used with the TARGET attribute by an anchor in our original document to change the location of the new window. Finally this line of code sets the width and height of the window and directs it not to display a menu bar.

Different objects support different methods, although you will find that some objects overlap in the methods they support. For example, almost every HTML element in Internet Explorer, including IMG, P, SPAN, DIV, and TABLE, supports the scrollIntoView method. If an element is not currently visible on the screen, this method causes the window to scroll until the element is in view. On the other hand, the createCaption method, which creates a CAPTION element for a table, is supported only by the TABLE object.

The window object supports many methods of general use. The following list provides some examples of these methods, supported in modern versions of both Internet Explorer and Netscape Navigator:

alert | Causes an Alert dialog box to appear, containing text and an OK button.
confirm | Causes a Confirm dialog box to appear, containing text and both an OK button and a Cancel button.
close | Used in a script to close a browser window that was opened through the open method.
open | Opens a new browser window.
prompt | Causes a Prompt dialog box to appear, containing text, OK and Cancel buttons, and a text input field.
setInterval | Causes a block of script or a function to be executed repeatedly (each time a specified time interval elapses).
setTimeout | Causes a block of script or a function to be executed once after a specified time interval has elapsed.

You can refer to Appendix C for a complete list of all the standard methods supported by Internet Explorer. Full descriptions of all methods can be found on the SBN Workshop Web site and on the CD that accompanies this book. On the CD see Workshop (References); DHTML, HTML & CSS; DHTML References; Methods. To get to the online version, visit the MSDN Online Resource page at http://msdn.microsoft.com/resources/schurmandhtml.htm, or open the file named MSDN_OL.htm on the companion CD, and choose DHTML Methods.

Using Methods to Create Dialog Boxes

Some of the most useful methods are alert, prompt, and confirm. These methods create dialog boxes, which allow the browser to interact with users. They are fully supported in versions 3 and later of both Internet Explorer and Netscape Navigator. Code Listing 7-4 demonstrates the use of all these types of dialog boxes. Figures 7-10 through 7-13 show the results.

Code Listing 7-4.

<HTML>
<HEAD>
<TITLE>Listing 7-4</TITLE>
</HEAD>
<BODY>
<FORM NAME="F1">
<INPUT TYPE="button"
  VALUE="alert button"
  onclick="alert(`You clicked the alert button.')">
<P>
<INPUT TYPE="button"
  VALUE="prompt button"
  onclick="document.F1.Text1.value=prompt(`Type below','Here')">
<INPUT TYPE="Text"
  NAME="Text1"
  SIZE="50"
  VALUE="Click each button, starting with the alert button.">
<P>
<INPUT TYPE="button"
  VALUE="confirm button"
  onclick="if(confirm(`Click OK')){alert(`Thank you.')}
    else{alert(`I said, CLICK OK!!!')}">
</FORM>
</BODY>
</HTML>

An Alert dialog box gives the user a message with an OK button. When you click the first button shown in Figure 7-10, the browser displays the Alert dialog box shown in Figure 7-11. You can close this dialog box by clicking the OK button or pressing the Enter key.

Click to view at full size.

Figure 7-10. Clicking any one of these three buttons produces a dialog box.

Click to view at full size.

Figure 7-11. An Alert dialog box.

A Prompt dialog box asks the user to provide information. Clicking the second button shown in Figure 7-10 runs a block of script that opens a Prompt dialog box (Figure 7-12) that asks the user to type some text in a text field. After the user types the text and clicks OK, the text field next to the Prompt button changes to the value typed in the Prompt dialog.

Click to view at full size.

Figure 7-12. A Prompt dialog box.

Notice that the first argument specified for the prompt method appears as instructions in the Prompt dialog box, while the second argument is the default text placed in the text entry area. The results of typing New Text into the text entry area can be seen behind the dialog box in Figure 7-13.

Click to view at full size.

Figure 7-13. A Confirm dialog box.

A Confirm dialog box presents the user with text as well as OK and Cancel buttons. This type of dialog box is useful when the user is being asked to make a decision. Clicking the third button shown in Figure 7-10 displays the Confirm dialog box (Figure 7-13), which is used as part of an if statement. The if statement in Code Listing 7-4 displays an Alert dialog box with the text Thank you if the expression inside its parentheses evaluates to true. It displays an Alert dialog box chastising the user if the expression evaluates to false. We use the confirm method for the expression. The Confirm dialog box returns true if the user clicks OK and false if the user clicks Cancel. Thus, a user who follows directions and clicks OK is rewarded with Thank you, while the user who clicks Cancel receives a stern reprimand.


Using Collections

A collection, as you learned in Chapter 5, is a numbered grouping of related items that are associated with an object. For example, in Internet Explorer versions 4 and later and in Netscape Navigator versions 3 and later the document object contains a collection named images, which refers to all the images on the page. The document object in Internet Explorer supports the all collection, which contains references to all the elements on the entire page. Another example is the cells collection of the TR element, which retrieves all the cells in a particular row of a table. A complete list of all the collections supported by Internet Explorer can be found in Appendix C. Detailed descriptions of the collections can be found on the SBN Workshop Web site and on the CD that accompanies this book. On the CD see Workshop (References); DHTML, HTML & CSS; DHTML References; Collections. Online, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm, or open the file named MSDN_OL.htm on the companion CD, and choose DHTML Collections.

Because collections are stored as numbered lists, you refer to an item in one of these lists with the collection name followed by the index (the numbered position of that item in the list) in parentheses. Collections are ordered using zero-based numbering: the index of the first item in the list is 0, the index of the second item is 1, and so on.

Code Listing 7-5 provides an example of three ways you can use the all collection, as well as an example of how to use the images collection. In Figure 7-14, you can see the initial display of this page. Figure 7-15 shows a dialog box containing all the tag names in the all collection, along with their indexes. In Figures 7-16 and 7-17, you can see how we used the all collection to change the images. Figure 7-18 shows what happens when the button is clicked and the image is changed through the images collection.

NOTE
If you are confused by the fact that collections are numbered starting with 0 rather than with 1, don't worry—you are joining the ranks of thousands of other confused individuals. In the programming world, most counting starts from 0. This, like many other seemingly strange programming practices, has its roots in binary mathematics, which is the basis of computing. Imagine a programmer from the 1950s who needs to make a list of all possible combinations that can be created with a set of bits, each of which can be either turned off or turned on. The first combination in the list has all the bits turned off. In binary counting, "all off" is represented by the numeral 0. The second combination has all but the first of the bits turned off. This combination is represented by the binary number 1. Thus, a confusing practice was born in which the first item in a list is numbered 0. But don't despair—you'll find that adapting to this system of counting is fairly easy.

Code Listing 7-5.

<HTML>
<HEAD>
<TITLE>Listing 7-5</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function doIt(){
  if (document.all){
    alert("First let's get a numbered list of all page elements.")

    strTagList=""
    for(i=0; i<document.all.length; i++) {
      strTagList+=(i+"\t"+document.all(i).tagName+"\n")
    }
    alert(strTagList)

    alert("Now change the second IMG using absolute index.")
    document.all(6).src="square.gif"

    alert("Finally, change the third IMG using relative index.")
    document.all.tags("IMG")(2).src="square.gif"
  }
}
</SCRIPT>
</HEAD>
<BODY>
<IMG SRC="circle.gif">
<IMG SRC="circle.gif">
<IMG SRC="circle.gif">
<FORM>
Use the all collection.
<INPUT TYPE="button" VALUE="Go" onclick="doIt()"><BR>
Use the images collection.
<INPUT TYPE="button" VALUE="Go" onclick="document.images[1].src=`x.gif'">
</FORM>
</BODY>
</HTML>

Click to view at full size.

Figure 7-14. The Internet Explorer window before any changes are made.

When the first button is clicked, its inline event handler calls the doIt function. This function first tests to see whether the all collection exists and proceeds only if it does. This is because Netscape Navigator and early versions of Internet Explorer might give errors if you try to use the all collection. If it does exist, an Alert dialog box notifies the user that a numbered list of all page elements is needed. When the user clicks OK, the function creates this list by using a for loop to go through the entire all collection, combining each element's position in the collection (its index) with its tag name and adding the result to the variable strTagList. (You'll learn more about for loops in Chapter 9 and examine variables and formatting tools such as \n in Chapter 8.) The for loop starts at 0 and goes through document.all.length, a property of the all collection that specifies how many items the all collection contains. The contents of the strTagList variable are then displayed in an Alert dialog box, as seen in Figure 7-15.

Click to view at full size.

Figure 7-15. This Alert dialog box lists each page element and its index.

When the user clicks OK, a new Alert dialog box appears, notifying the user that the second image will change. Once the user clicks the OK button in this new dialog box, the image is referred to by its index within the all collection. As indicated in the list of tags (see Figure 7-15), the second image is in position 6 in the list. Thus, we can use the expression document.all(6) to refer to it. We then use this reference to change the src property of the image, altering its appearance as shown in Figure 7-16.

Another way of referring to an item in the all collection is by specifying its location relative to other tags of its type. The tags method of the all collection returns another collection of all the tags of a specified name. We can use this method to get a collection of all the IMG tags and then change the third item in this new collection:

document.all.tags("IMG")(2).src="square.gif"

Click to view at full size.

Figure 7-16. The all collection was just used to alter the item at index 6 (the second image). Next the third image will be changed.

Because collections are zero-ordered, the third image is at index 2 in the collection of IMG tags. You can see the effects of this code in Figure 7-17.

Click to view at full size.

Figure 7-17. The all collection is used with the tags method to alter the third image.

Another common collection used in Netscape Navigator versions 3 and later and in Internet Explorer versions 4 and later is document.images. This is essentially a preexisting collection that is the same as the one returned by document.all.tags("IMG") in Internet Explorer. Figure 7-18 shows the effects of clicking the second button on the page, which changes one of the images using the images collection. This button has the same effect in both browsers.

Click to view at full size.

Figure 7-18. The images collection is used to alter the second image.

This chapter has focused on how script can interact with the Object Model. Next we will deal with script in a more pure form. The following chapter explains the types of data found in JScript, as well as how to manipulate that data.


Chapter 8 -- Working with Data

 Chapter 8

Working with Data

One fundamental purpose of all programming is to manipulate or present data. The scripting languages in Microsoft Internet Explorer 5 (VBScript and JScript) are designed to accomplish this on a Web page. In this chapter, we will explain how to work with variables, data, and data manipulation tools in JScript.


Variables

Strictly speaking, variables are not data. They are, however, so completely intertwined with data manipulation that it is nearly impossible to speak of one and not the other. A variable is a named object that refers to or contains data; in fact, you can think of a variable as a container. For example, the following line assigns the value 2 to a variable named myVar.

myVar=2

You can also set one variable equal to the value of another variable. In the following example, the variable num1 is assigned the value 50. Another variable, named num2, is then assigned the value of the variable num1.

num1=50
num2=num1

The value of the second variable, num2, is now 50.

Because JScript is a case-sensitive language, you must be careful how you refer to variables; num1, Num1, and NUM1, for example, would name three different variables. If we had set num2=Num1 in the preceding example, an error would have resulted because our variable was named num1, not Num1.

Variables are so named because the values they contain can change. In the following lines of code, the value assigned to the variable myVar changes three times.

myVar=10
myVar=someOtherVar
myVar=75

After these three operations, the final value myVar is 75.

Declaring Variables

Many programming languages require the programmer to create, or declare, variables before using them. These languages generate an error if you try to use an undeclared variable. In JScript, however, it is usually unnecessary to explicitly declare variables, although it is considered good practice. To declare a variable, you use the var keyword. The following example declares two variables, myVar and anotherVar, and assigns an initial value of 50 to anotherVar (a process referred to as initializing the variable).

var myVar
var anotherVar=50

The only time that you must declare a variable in JScript is when you want to create a variable that has only local scope. A variable with local scope is available only inside the function in which it is declared. Using variables with local scope, when possible, helps to reduce memory consumption and can result in performance improvements. Explicitly declaring variables also can make your code easier to debug. If you do not explicitly declare a variable, or if you declare it outside a function, it is said to have global scope, which means that it can be written to or accessed by code anywhere in the program.


Types of Data

In JScript, the data contained in a variable can be one of six types: string, number, Boolean, null, undefined, and object. Each data type is suited for a specific purpose. Unlike most programming languages, JScript is not strongly typed—that is, in JScript the same variable can contain one type of data, such as a string, at one time and another type, such as a number, at a later time. The sections that follow take a closer look at each type of data.

String Data Type

A string is a series of characters, which can include letters, numbers, and symbols. A string is separated from the surrounding code with either single or double quotation marks. For instance, the following lines of code are equivalent; each assigns the same value to a variable named myVar:

myVar="This is a string"
myVar=`This is a string'

NOTE
Let's define some basic terminology: a character is any letter, number, or symbol; a letter is any member of the alphabet (uppercase or lowercase); a number is one or more digits; and a symbol is any nonletter, nonnumber character, such as a punctuation mark.

Strings in JScript are made up of unicode characters. Unicode is a standard that defines thousands of characters from many languages. A string can be millions of characters long—although any script using such a string probably would perform very slowly.

If you want to include either single or double quotation marks as part of the string itself, you can simply use the other set of quotation marks to define the string. For example, the following line of code assigns the string value He said, "Hello!" to the variable myVar:

myVar=`He said, "Hello!"`

You can also represent quotation marks and certain other characters by using escape sequences. An escape sequence is simply a special code for a character. Escape sequences are generally used for two purposes:

  • To signify that a character normally used in the context of program code is instead being used as part of a string (for instance, when you want double quotation marks to appear as part of a string even though the string itself is enclosed in double quotation marks)

  • To include control sequences that do not usually have character equivalents, such as a carriage return

Escape sequences consist of a character preceded by a backslash. Here are the characters for which JScript provides string escape sequences.

Character | Escape Sequence
single quotation mark | \'
double quotation mark | \"
backslash | \\
backspace | \b
carriage return | \r
form feed | \f
new line (linefeed) | \n
tab | \t

The following line of code demonstrates some of these escape sequences:

myVar="Here are some special characters - \\,\",\'."

In this line, the variable myVar is assigned the string Here are some special characters - \, ", `.

NOTE
In addition to supporting escape sequences in JScript, browsers can display foreign language letters, special characters, and symbols through the use of character entities. For instance, the character entity &nbsp; represents a nonbreaking space. Find out more about character entities on the SBN Workshop Web site and on the CD that accompanies this book. On the CD see Workshop (References); DHTML, HTML & CSS; HTML References; Character Sets. To get to the online version, visit the MSDN Online Resource page at http://msdn.microsoft.com/resources/schurmandhtml.htm, or open the file named MSDN_OL.htm on the companion CD, and choose Character Sets.

Number Data Type

You can also represent data in JScript as an integer (a whole number, such as 2) or as a floating-point number (a number containing a decimal point, such as 54.686). These numbers are normally shown in base 10 (standard decimal numbers), but they can also be represented in scientific notation, in base 8 (octal), or in base 16 (hexadecimal). The following lines of script demonstrate these different ways of expressing numbers:

varInDecimal=46
varInScientific=4.6e1
varInOctal=056
varInHexadecimal=0x2e

Each of these variables is assigned the same value, 46. (You can find a full explanation of each type of number at the Microsoft Developer Network (MSDN). To get there, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm, or open the file named MSDN_OL.htm on the companion CD, and choose JScript Data Types.)

Many languages have several distinct data types to represent numbers. In these other languages, you must specify whether a variable is to be of integer type or floating-point type, and thereafter you can use that variable only for that type of numeric data. JScript, however, provides only one number data type that allows both types of numeric data. In fact, a single variable can contain an integer value at one time and a floating-point value at another.

In addition to numeric values, there are several special values available for variables of type number, as shown in Table 8-1.

Table 8-1 Special Values for Variables of Type Number

Variable | Value
Infinity | Infinity. Treated as positive infinity for mathematical operations.
+Infinity | Explicit Positive Infinity. Treated as positive infinity for mathematical operations.
-Infinity | Negative Infinity. Treated as negative infinity for mathematical operations.
+0 | Positive Zero. Assigns positivity to this normally signless value.
-0 | Negative Zero. Assigns negativity to this normally signless value.
NaN | Not a Number. This value can be assigned, or it can be the result of mathematical operations. For example, -Infinity divided by +Infinity results in NaN.

Boolean Data Type

Boolean data can have one of only two possible values, true or false. Unlike some other languages, such as many versions of C and C++, in which Boolean data types are simulated, using 0 for false and 1 or nonzero for true, JScript provides a genuine Boolean data type. Boolean data is commonly used to perform tests that determine whether an action will take place. For example, you can create a conditional statement that will perform one action if a Boolean value is true and another if it is false. Chapter 9 discusses the use of Boolean values with conditional statements.

Null Data Type

The null data type is actually both a value and a data type. Setting a variable to null explicitly states that the variable has no value. It also specifies that the variable is not one of the other data types, such as a string or a number. The following line of code assigns a null value to the variable myVar:

myVar=null

Notice that although null is a data type in JScript, this is not the case in some other languages where null is simply equivalent to 0. This data type is frequently used in error handling, as is undefined.

Undefined Data Type

The undefined data type is a special type that cannot be assigned to a variable. Instead, a variable is considered to be of the undefined type if it has not been declared, or if it has been declared but does not have a value. You will frequently see an error message saying that a variable is undefined if you try to use a variable that has not been previously set to a value. For instance, the line var1=var2 results in the error `var2' is undefined if var2 has not been previously defined and set to a value.

Code Listing 8-1 demonstrates the data types we've discussed so far. Figure 8-1 shows the display that results when the browser processes this code.

Code Listing 8-1.

<HTML>
<HEAD>
<TITLE>Listing 8-1</TITLE>
<SCRIPT LANGUAGE="JavaScript">
var a="\"word\""
var b=32
var c=true
var d=null
var e
document.write("a="+a+", b="+b+", c="+c+", d="+d+", and e="+e)
</SCRIPT>
</HEAD>
</HTML>

Click to view at full size.

Figure 8-1. Displaying different data types.

In Code Listing 8-1 and Figure 8-1, variable a contains a string value, b a number value, c a Boolean value, d is set to null, and e is not given a value. Notice the plus signs in the line of code that begins with document.write. These plus signs join the different strings on the line to create one large string, which is then written to the screen as HTML by the document.write() method. (Later in this chapter, we will discuss using plus signs and other operators.)

Object Data Type

The final data type supported by JScript is object. This category is wide and varied. For example, there is an array object that allows you to group pieces of data and a date object that is useful for storing dates and times. You can also construct your own custom objects as well as assign Object Model objects to JScript variables. Code Listing 8-2 provides a demonstration of assigning an object in the Object Model to a variable. Figure 8-2 shows the resulting display.

Code Listing 8-2.

<HTML>
<HEAD>
<TITLE>Listing 8-2</TITLE>
</HEAD>
<BODY>
Here is a text input.
<FORM NAME="F1">
<INPUT NAME="T1" TYPE="text" VALUE="foo">
<SCRIPT LANGUAGE="JavaScript">
  a=document.forms[0].elements[0]
</SCRIPT>

<INPUT TYPE="button" VALUE="Display Value" onclick="alert(a.value)">
</FORM>
</BODY>
</HTML>

Click to view at full size.

Figure 8-2. Accessing the Object Model. Clicking the Display Value button displays the value of the text input.

The script shown in Code Listing 8-2 contains a form that, in turn, contains a text box. This text box is represented as an object in the Object Model. We assign the text box object to the JavaScript variable a with the code a=document.forms[0].elements[0]. Thereafter, we can refer to the text box simply as a, which is not only easier to type and understand but can also result in substantial speed increases in the script if the object is referred to multiple times. Consequently, the code a.value now refers to the value property of the text box object—and when the Display Value button is pressed, the browser displays the value of the text box's value property. Also notice that you can change the contents of the text box; click the Display Value button again, and the browser displays a dialog box containing updated contents of the text box.

You can create your own JScript objects using the new operator. Like the built-in objects in the Object Model, these objects can have their own properties and methods. In Code Listing 8-3, an object is created and properties are assigned to it. You can see the result in Figure 8-3.

NOTE
The Document object has a collection called forms, which refers to all of the forms in the current document. Each item in this collection, in turn, has a collection called elements, which simply represents all of the elements (INPUTs, SELECTs, and so on) in that form. The object name document.forms[0].elements[0] is the most generic and cross browser/platform/version way of referring to the input in our example. If we were developing only for Internet Explorer 4 or later, we could simply use the expression a=F1.T1, because of the Internet Explorer enhanced object model.

Code Listing 8-3.

<HTML>
<HEAD>
<TITLE>Listing 8-3</TITLE>
<SCRIPT LANGUAGE="JavaScript">
var Stu1=new Object
Stu1.name="John Doe"
Stu1.test1="B+"
Stu1.test2="A-"
document.write("There is an object called Stu1<BR>")
document.write("Its name property equals "+Stu1.name+"<BR>")
document.write(Stu1.name+"`s score on test1: "+Stu1.test1+"<BR>")
document.write(Stu1.name+"`s score on test2: "+Stu1.test2+"<BR>")
</SCRIPT>
</HEAD>
</HTML>

Click to view at full size.

Figure 8-3. Creating an object.

With the code var Stu1=new Object in Code Listing 8-3, an object named Stu1 is created. We then assigned values to some new properties of the Stu1 object, name, test1, and test2. Thereafter, we can access these values by referring to these properties of the Stu1 object.

Constructor Functions

JScript supports the use of constructor functions, which can be used to easily create large groups of objects that you define. The following snippet of code results in a constructor function used to create the type of object used in Code Listing 8-3.

function makeStudent(strName, strTest1, strTest2){
  this.name=strName
  this.Test1=strTest1
  this.Test2=strTest2
}

The object itself can then be created with the following line of code:

Stu1=new makeStudent(`John Doe','B+','A-')

Additional objects can be created easily, as follows:

Stu2=new makeStudent(`Jim Smith','B','B-')
Stu3=new makeStudent(`Lori James','B-','C-')
Stu3=new makeStudent(`Jane Doe','A+','A')

Array Objects

An array object can be thought of as a numbered list of associated pieces of data. Each piece of data is an element of the array and has an associated index number. Arrays are zero-ordered (numbered starting with 0). You can refer to a particular element in an array by using the name of the array and the index number of the element enclosed in brackets. Thus, in an array named myArray, you refer to the first item in the array as myArray[0]; the second item is myArray[1]. You can create an array with the new operator, as we do in Code Listing 8-4, and then populate it with data. The results are displayed in Figure 8-4.

Code Listing 8-4.

<HTML>
<HEAD>
<TITLE>Listing 8-4</TITLE>
<SCRIPT LANGUAGE="JavaScript">
var nameList=new Array
nameList[0]="John"
nameList[1]="Mary"
nameList[49]=3774
document.write("The first value is "+nameList[0]+"<BR>")
i=49
document.write("The value at index "+i+" is "+nameList[i]+"<BR>")
i=25
document.write("The value at index "+i+" is "+nameList[i]+"<BR>")
</SCRIPT>
</HEAD>
</HTML>

Click to view at full size.

Figure 8-4. Using an array.

In JScript, each element of an array can contain a different type of data. Note that the array in Listing 8-4 contains both strings and a number. In addition, an array does not need to contain an element at every index location. This is why we can skip from index 1 to index 49 in Code Listing 8-4. Elements that are skipped have a value of undefined.

NOTE
Arrays and objects are similar in JScript. In fact, you can name the indexes of an array with words rather than with numbers—for instance, nameList["name1"]="John". From then on, you can refer to this element either with array notation (nameList["name1"]) or with the standard dot notation commonly used with objects (nameList.name1).


Manipulation of Variables and Data

Now that you have learned a little about variables and data, you need to know how to work with them. The two basic tools for manipulating data are operators and methods.

Operators

JScript allows the creation of mathematical expressions. An expression is essentially a mathematical sentence—for example, 5+6 or myVar+4. An operator is like a verb in the sentence; it performs an action. In the expression 5+6, the plus sign is the operator because it performs the action of adding the two numbers. Table 8-2 describes common mathematical operators.

Table 8-2 Common Mathematical Operators

Operator | Action Performed
= | Assignment. Assigns a value or an expression to a variable. For example, myVar=6 assigns the value 6 to the myVar variable.
+ | Addition or concatenation. Adds two values or combines (concatenates) two strings. For example, 1+2 equals 3, and "sample"+"text" equals "sampletext".
- | Subtraction. Subtracts one number from another.
- | Unary negation. Makes the associated value a negative value. For example, -3 is read as "negative three."
/ | Division. Divides one number by another.
* | Multiplication. Multiplies one number by another.
% | Modulo. Returns the remainder when one number is divided by another. For example, 7%4 equals 3.
+=, -=, *=, /=, %= | Arithmetic operation with assignment. Performs an action with the contents of a variable and assigns the result to the variable. For example, if the variable myVar has a value of 5, the expression myVar+=6 adds 6 to the value; as a result, the value of myVar now equals 11. Thus, the expression myVar+=6 is equivalent to myVar=myVar+6. When it is used with strings, the operator += concatenates one string with another. For example, if the value of myVar equals "sample", the expression myVar+="text" changes the value of myVar to "sampletext".
++ | Increment. Adds 1 to a value. For example, if the value of myVar is 6, the expression myVar++ changes that value to 7. Thus, the expression myVar++ is equivalent to myVar=myVar+1.
-- | Decrement. Subtracts 1 from a value. For example, if the value of myVar is 6, the expression myVar-- changes that value to 5. Thus, the expression myVar-- is equivalent to myVar=myVar-1.
( ) | Group. Used to group parts of an expression. For example, the expression 4+(6/2) divides 6 by 2 and then adds the result to 4, resulting in a value of 7. In contrast, the expression (4+6)/2 adds 4 and 6 and then divides the result by 2, resulting in a value of 5.

Code Listing 8-5 demonstrates the use of the + operator. When the browser processes this code, you see the display shown in Figure 8-5.

Code Listing 8-5.

<HTML>
<HEAD>
<TITLE>Listing 8-5</TITLE>
<SCRIPT LANGUAGE="JavaScript">
var a=15
var b=`abc'
var c=`10'
var d=true

document.write("Variable a=15, b=`abc', c=`10' and d=true<BR>")
document.write("a+10 equals "+(a+10)+"<BR>")
document.write("b+'def' equals "+(b+'def')+"<BR>")
document.write("c+a equals "+(c+a)+"<BR>")
document.write("b+d equals "+(b+d)+"<BR>")
document.write("a+d equals "+(a+d)+"<BR>")
</SCRIPT>
</HEAD>
</HTML>

Click to view at full size.

Figure 8-5. Using the + (addition or concatenation) operator.

The first mathematical expression is a+10. Because the variable a has been assigned the value 15, the expression a+10 adds the number 10 to the number 15, resulting in a value of 25. In the next line, we add the letters def to the end of variable b (a string containing the letters abc), resulting in the string abcdef. (In other words, the two strings are concatenated.)

The next three lines illustrate what happens when you try to add variables that are of different data types. When a string is added to a nonstring, the nonstring is usually converted to a string and the two are then concatenated. For instance, the expression c+a, in which c is a string containing the two characters 1 and 0 (10) and a is the number 15, results in the string 1015. In the next line, the Boolean variable d (which has been assigned the value true) is added to string b (which has the string value abc), resulting in the string abctrue. (The Boolean value is converted to a string and then concatenated to the value of variable b.) Finally you can see the results of adding a Boolean variable to a number type. The expression a+d is the equivalent of 15+true. In such an operation, a Boolean value of true is treated as 1, while false is treated as 0. Thus, the expression 15+true evaluates to 16.

Type Conversion

Although it is often useful to have JScript automatically convert one type of data to another, you might not always want such a conversion to occur. Several built-in methods let you control data type conversion, ensuring that data ends up in the desired type.

You can determine the current type of a variable by using the typeof operator. This operator returns one of six possible values: string, number, Boolean, object, function, and undefined. Code Listing 8-6 demonstrates the typeof operator in use. Figure 8-6 shows how the browser displays the results of this code.

Code Listing 8-6.

<HTML>
<HEAD>
<TITLE>Listing 8-6</TITLE>
<SCRIPT LANGUAGE="JavaScript">
var a=15
var b=`abc'
var c=`10'
var d=true
var e=window
var f

document.write("Variable a=15, b=`abc', c=`10', d=true, ")
document.write("e=window, and f is not equal to anything.<BR>")
document.write("a is of type "+typeof(a)+"<BR>")
document.write("b is of type "+typeof(b)+"<BR>")
document.write("c is of type "+typeof(c)+"<BR>")
document.write("d is of type "+typeof(d)+"<BR>")
document.write("e is of type "+typeof(e)+"<BR>")
document.write("f is of type "+typeof(f)+"<BR>")
</SCRIPT>
</HEAD>
</HTML>

Click to view at full size.

Figure 8-6. Using the typeof operator.

Another way to test a variable or an expression is by using the isNaN method. This test returns true if the item evaluated is not a number (and cannot be expressed as a number) and returns false if it is a number. To test a variable or an expression, enclose it in parentheses after the isNaN method is called (making it an argument passed to the isNaN method). Thus, isNaN("test") returns true because "test" is a string and is not a number. The expression isNaN(13) returns false because 13 is a number, whereas isNaN("13") returns false because even though 13 (in quotation marks) is a string, it can be expressed easily as a number. If a variable a has the value 13, the expression isNaN(a) is the equivalent of isNaN(13) and evaluates to false because 13 is a number.

You can change a string to a number using the parseInt method or the parseFloat method. The parseInt method discards any characters after the first nonnumber character (even a decimal point) in a string. The parseFloat method works the same way except that it retains an existing decimal point. A number (or other data type) can be converted to a string with the toString method, which is a built-in method of all standard data types.

Code Listing 8-7 demonstrates the use of these methods to manipulate variables before adding them together. The results are shown in Figure 8-7.

Code Listing 8-7.

<HTML>
<HEAD>
<TITLE>Listing 8-7</TITLE>
<SCRIPT LANGUAGE="JavaScript">
var a=15
var b=`10.5'
var c=`12a5'
document.write("Variable a=15, b=`10.5', and c=`12a5'<BR>")
document.write("isNaN(a) evaluates to "+isNaN(a)+"<BR>")
document.write("isNaN(b) evaluates to "+isNaN(b)+"<BR>")
document.write("isNaN(c) evaluates to "+isNaN(c)+"<BR>")
document.write("a+b equals "+(a+b)+"<BR>")
document.write("a+parseInt(b) equals "+(a+parseInt(b))+"<BR>")
document.write("a+parseFloat(b) equals "+(a+parseFloat(b))+"<BR>")
document.write("a+parseInt(c) equals "+(a+parseInt(c))+"<BR>")
document.write("a+parseFloat(c) equals "+(a+parseFloat(c))+"<BR>")
document.write("a+a equals "+(a+a)+"<BR>")
document.write("a+a.toString() equals "+(a+a.toString())+"<BR>")
</SCRIPT>
</HEAD>
</HTML>

Click to view at full size.

Figure 8-7. Effects of converting one data type to another.

Notice that when we use parseInt on variable b in Code Listing 8-7, the resulting value is a whole number, whereas using parseFloat results in a number with a decimal point. Also notice that in the last expression in this sample, we add the variable a (which is a number) to a expressed as a string, which results in a concatenated string.

NOTE
You can convert a string to an array and vice versa with the split and join methods. These methods take a single string as an argument. The code myArray=myString.split(",") will convert myString to an array and assign the results to myArray. The contents of myString before the first comma (the argument passed to the split method) will be assigned to myArray[0], the contents between the first and second commas to myArray[1], and so on. The join method performs the opposite action and combines the elements of an array into a single string, separated by the character or characters passed as an argument. To learn more about these methods, consult the Microsoft Developer Network Scripting Web site. To get there, visit the MSDN Online Resource page at http://msdn.microsoft.com/resources/schurmandhtml.htm, or open the file named MSDN_OL.htm on the companion CD, and choose JScript Language Reference.

Methods and Properties of Data Types

Each data type supports its own special methods and properties. As you will remember, methods are actions that can be performed on the data; properties give us information about the data. Virtually all data objects support the toString method, discussed earlier, and the valueOf method, which returns the value of the object. A useful property is length, which acts differently depending on the type of data.

The following sections take a brief look at some of the methods and properties supported by various data types. You can find details about all these methods and properties on the Microsoft Developer Network Scripting Web site; see msdn.microsoft.com/scripting.

Strings

Variables of the string type can use the methods shown in Table 8-3.

Table 8-3 Methods for Variables of Type String

anchor | FromCharCode | Split
big | IndexOf | strike
blink | Italics | sub
bold | LastIndexOf | substr
charAt | Link | substring
charCodeAt | Match | sup
concat | Replace | toLowerCase
fixed | Search | toUpperCase
fontcolor | Slice | toString
fontsize | Small | valueOf

These methods are used in the same way as methods in the Dynamic Object Model are, and they are executed in code using standard dot notation. For example, given a variable named myString, the code myString.toLowerCase() applies the toLowerCase method to myString, setting all text contained in the variable myString to lowercase.

Code Listing 8-8 provides examples of some of the most useful of these methods. To see what they produce, refer to Figure 8-8.

Code Listing 8-8.

<HTML>
<HEAD>
<TITLE>Listing 8-8</TITLE>
<SCRIPT LANGUAGE="JavaScript">
var a="Fourscore and seven years ago..."
doc=document

doc.write("a is a string equal to <B>"+a+"</B>")
doc.write("<BR>")
doc.write("a.charAt(3) is <B>"+a.charAt(3)+"</B>")
doc.write("<BR>")
doc.write("a.indexOf(`and') is <B>"+a.indexOf(`and')+"</B>")
doc.write("<BR>")
doc.write("a.lastIndexOf(`s') is <B>"+a.lastIndexOf(`s')+"</B>")
doc.write("<BR>")
doc.write("a.replace(`Four','Two') is <B>"+a.replace(`Four','Two')+"</B>")
doc.write("<BR>")
doc.write("a.substring(3,12) is <B>"+a.substring(3,12)+"</B>")
doc.write("<BR>")
doc.write("a.length is <B>"+a.length+"</B>")
</SCRIPT>
</HEAD>
</HTML>

In Code Listing 8-8, the charAt method returns the character that is found at a particular location (index) in the string. Because strings are zero-ordered, the code charAt(3) returns the fourth character in the string. The indexOf method searches through the string and returns the first position of a specified character or characters within that string. The lastIndexOf method searches the string backward for a character or characters. To replace one set of characters in a string with another, we used the replace method (replacing Four with Two). The substring method returns a part of the string, given a start and an end point. The length property returns the number of characters in the string.

Click to view at full size.

Figure 8-8. Using string methods.

Numbers and Booleans

Numbers and Boolean variables support only the toString and valueOf methods. They do not support a length property.

The Math Object

In addition to the toString and valueOf methods, a useful way to manipulate numbers in JScript is with the Math object. This object supports many methods that perform mathematical operations on numbers; for example, you can use the pow method to raise a number to a power or the cos method to take the cosine of a number. Here is a list of the methods supported by the Math object:

abs | acos | asin | atan | atan2 | ceil
cos | exp | floor | log | max | min
pow | random | round | sin | sqrt | tan

Some of these methods are shown in Code Listing 8-9. The display in Figure 8-9 illustrates how they work.

Code Listing 8-9.

<HTML>
<HEAD>
<TITLE>Listing 8-9</TITLE>
<SCRIPT LANGUAGE="JavaScript">
var a=2.767

document.write("a is a number equal to "+a+"<BR>")
document.write("Math.cos(a) equals "+Math.cos(a)+"<BR>")
document.write("Math.pow(a,2) equals "+Math.pow(a,2)+"<BR>")
document.write("Math.floor(a) equals "+Math.floor(a)+"<BR>")
document.write("Math.round(a) equals "+Math.round(a)+"<BR>")

document.write("Math.random() equals "+Math.random()+"<BR>")
document.write("Math.random() equals "+Math.random()+"<BR>")
document.write("Math.random() equals "+Math.random()+"<BR>")
</SCRIPT>
</HEAD>
</HTML>

Click to view at full size.

Figure 8-9. Using the Math object.

The first use of the Math object in Code Listing 8-9 finds the cosine of the value of variable a, using the cos method. Next we use the pow method to raise a to the second power, which returns the value of a squared. The floor method removes any digits after the decimal point, while the round method rounds a to the nearest whole number. The random method returns a randomly generated number between (and including) 0 and 1 each time the method is called; notice that each instance of random results in a different number.

Arrays

Arrays support the concat, join, reverse, slice, and sort methods. You can use the concat method to combine two arrays into one. The join method creates a string from all the elements in the array, separated with a dividing character that you specify. The reverse method reverses the order of the elements of the array. The slice method returns part of an array. The sort method lets you reorder the elements of an array. The length property returns the number of elements in the array. For example, if an array has indexes numbered 0 through 9, its length will be 10. This is true even if some of the indexes in the range are undefined.

This chapter has laid the foundation for working with data in JScript. In the next chapter, we will look at how to control the flow of your JScript programs through the use of functions, which package blocks of script into easily addressable units, and conditional statements, which let your script react differently in different situations. We will also look at loops, which offer a simple way to repeat actions.


Chapter 9 -- Functions, Conditionals, and Loops

 Chapter 9

Functions, Conditionals, and Loops

Programs are written to perform actions. This chapter takes a look at several ways to control these actions. First we will look at functions, which allow you to group sets of actions together and run them as a block. Next we'll discuss conditional statements, which let you specify conditions that must be met for an action to take place. Finally we will examine the various types of loops, which allow you to easily repeat actions.


Functions

Programs often need to perform a particular set of actions under many different circumstances. A function is a named block of program code that can be run at any time simply by calling the function's name. As you learned in Chapter 6, you can define a function in JScript by using the function keyword followed by the name of the function and a set of parentheses. The block of script enclosed in curly braces ( { and } ) that follows the parentheses defines the actions that the function will perform. For instance, the following code creates a function named greetUser that contains script to display in an Alert dialog box:

function greetUser(){alert("Hi there. This is a dialog box.")}

The greetUser function can now be called at any time by using its name (including the parentheses). For instance, the following BUTTON tag has an embedded event handler that calls the greetUser function whenever the button is clicked:

<BUTTON onclick="greetUser()">Hello</BUTTON>

NOTE
One somewhat unusual feature of JScript is that functions can be treated like variables or data. Because of this, you can use functions in ways that are not possible in many other programming languages. For example, one function can be passed to another function as an argument, or different indexes of an array can be assigned different functions.

Arguments

Arguments, which are placed in the parentheses following the function name, provide a mechanism by which information is passed to a function. You can pass multiple arguments to a single function by separating them with commas. Code Listing 9-1 demonstrates the use of a function with two arguments. In Figure 9-1, you can see what the browser displays after one of the buttons specified in the code has been pressed.

Code Listing 9-1.

<HTML>
<HEAD>
<TITLE>Listing 9-1</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function changeIt(target,newText){
  oldText=target.value
  target.value=newText
  alert("The button that read `"+oldText+"` now reads `"+newText+"`.")
}
</SCRIPT>
</HEAD>
<BODY>

<FORM>
  <INPUT TYPE="button" VALUE="Btn1" onclick="changeIt(this,'One')"><BR>
  <INPUT TYPE="button" VALUE="Btn2" onclick="changeIt(this,'Two')"><BR>
  <INPUT TYPE="button" VALUE="Btn3" onclick="changeIt(this,'Three')"><BR>
</FORM>

</BODY>
</HTML>

Click to view at full size.

Figure 9-1. An Alert dialog box appears after a button is clicked.

In Code Listing 9-1, we initially set the text of each of the buttons with the VALUE attribute. Each button has an onclick event handler that calls the changeIt function when the element is clicked. Two arguments are passed to the changeIt function: the first is the keyword this (which returns the current object), and the second is the new text that we want in the button.

The passed values are assigned to the target and newText variables in the function, in that order. The function first saves the old value of the button in a variable named oldText that is used later in an alert. The target and newText variables are used to change the text of the clicked button and to alert the user to what has occurred.

Also notice that when we passed arguments when calling the changeIt function, the second argument appeared in quotation marks, while the first argument did not. Enclosing an argument in quotation marks means that the argument should be treated as a string. You do not use quotation marks when passing a non-string type, such as a number, an object, or a variable (even a variable that contains a string). The first argument passed in Code Listing 9-1 is a reference to the object that was clicked. Passing a reference to the button itself allows access to the button's properties directly through the function's target variable. If we had enclosed the word this in quotation marks, we would have simply passed to the function a string containing the letters t, h, i, and s rather than the object itself. A real-world equivalent might be the difference between giving someone a car and telling the person the name of the car. The second argument we passed is a string containing the text we want for the button.

Returns

You just saw how to pass data to a function by using arguments. To get information back from a function, you can use a return. The return keyword causes a function to evaluate to a result—that is, to "return" a value when it is run. You can use this mechanism to assign the return value of a function to a variable or use the returned value in some other way. Code Listing 9-2 demonstrates the use of a return value; in Figure 9-2, you can see what this code does.

Code Listing 9-2.

<HTML>
<HEAD>
<TITLE>Listing 9-2</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function rndNum(maxNum){
  num=Math.random()
  num=num*maxNum
  num=Math.ceil(num)
  return num
}
function tellUser(specifiedNum){
  alert(rndNum(specifiedNum))
}
</SCRIPT>
</HEAD>
<BODY>

Type a number in the area below, and then click Calculate.<BR>
The page will generate a random number between 1 and the
number you entered.<BR>

<FORM>
<TEXTAREA NAME="TextNum">10</TEXTAREA>
<BR>
<INPUT TYPE="button" VALUE="Calculate"
       onclick="tellUser(TextNum.value)">
</FORM>
</BODY>
</HTML>

Click to view at full size.

Figure 9-2. Retrieving a value from a function.

Code Listing 9-2 illustrates how an argument is passed to a function, how one function can call another, and how the return keyword is used. Clicking the Calculate button calls the tellUser function, passing the value of the TEXTAREA named TextNum as an argument. The tellUser function then produces an Alert dialog box. This dialog box displays the value returned by the rndNum function, which first generates a random number between 0 and 1, multiplies that number by the argument that was passed to it, and then rounds the resulting number upward. This final value is returned to the tellUser function and is then displayed on screen in the Alert dialog box.

NOTE
Code Listing 9-2 should work in Netscape Navigator or Microsoft Internet Explorer versions 4 or later. To do the same thing in the version 3 browsers, you cannot use the simple syntax TextNum.value to refer to the number in the text area. Instead, you should use the older syntax document.forms[0].elements[0].value to accomplish the same goal. Another difference between browsers is that Internet Explorer does not require the FORM tags around the INPUT and also allows a BUTTON tag to be used instead.

If you were designing a similar Web page that was destined for the real world, you would want to do some error checking to ensure that the data being passed to the function was a number. In Code Listing 9-2, if you use a letter or a word instead of a number, the page displays NaN, which means that the value passed was not a number. In the next section, we will explore methods of testing data that can be used for error checking.


Conditionals

Conditional statements let you specify the conditions that must be met before an action can take place. The conditions themselves are normally logical expressions that evaluate to a Boolean value. Before we delve any deeper into conditionals, we should take a closer look at Boolean data and operations.

`

Boolean Comparisons

Boolean expressions, which can have only one of two values (true or false), are especially helpful when used with conditional statements. You can assign a Boolean value to a variable as follows:

myVar=true

As you saw in Chapter 8, you can use mathematical operators for mathematical expressions; for instance, you can use the addition operator to write the expression 4+4, which evaluates to 8. In the same way, you can use logical operators for Boolean expressions; for example, the expression 4==4 evaluates to true.

Notice the two equal signs in the Boolean equality expression. A single equal sign is an assignment operator; it assigns one value to another. The equality operator is composed of two equal signs; it tests the values on each side and results in a Boolean value of true if the values are equal and a value of false if they are not. Thus, the expression 4==5 evaluates to false, whereas 4==4 evaluates to true. Another frequently encountered logical operator is the inequality operator, !=, which tests whether two values are not equal. For example, the expression 4!=5 evaluates to true because it is true that 4 does not equal 5. These types of tests are known as Boolean, logical, or conditional operations. Table 9-1 describes a number of the most common logical operators.

Table 9-1 Common Logical Operators

Operator | Test Performed
== | Equality. Tests whether one value is equal to another. For example, if x is equal to the number 4, these three statements all evaluate to true: x==4, x=="4", and false==false. In the second expression, the string 4 is automatically converted to a number when it is compared. (See Chapter 8 for more information about data conversion.)
!= | Inequality. Tests whether two values are not equal. For example, the statement 4!=5 evaluates to true, and 4!=4 is false.
< | Less than. Tests whether a value is less than another value. For example, if x is equal to 4, the expression x<5 is true, the expression x<4 is false (because 4 is not less than 4), and the expression x<3 is false.
> | Greater than. Tests whether a value is greater than another value. For example, if x is equal to 4, the expression x>5 is false and the expression x>3 is true.
<= | Less than or equal to. Tests whether a value is less than or equal to another value. For example, if x is equal to 4, the expression x<=5 is true, the expression x<=4 is true, and the expression x<=3 is false.
>= | Greater than or equal to. Tests whether a value is greater than or equal to another value. For example, if x is equal to 4, the expression x>=5 is false, the expression x>=4 is true, and the expression x>=3 is true.
! | NOT. Reverses the value of a Boolean expression. For example, if x is equal to true, the expression !x evaluates to false and the expression !(4==5) evaluates to true.
&& | AND. Compares two Boolean expressions, and if both expressions are true the operation returns true; if either is false, it returns false. For example, the expression (4==4)&&(4<5) evaluates to true. If the variable hungry is true and the variable haveFood is false, and if canEat equals hungry&&haveFood, then canEat evaluates to false.
|| | OR. Compares two Boolean expressions, and if either expression is true the operation returns true; only if both are false does it return false. For example, if x equals 4 and y equals 5, the expression (x==4)||(y==4) equals true and the expression (x= =3)||(y= =4) equals false.
=== | Identity. Tests whether two values are not only equal but also of the same type. For example, the expression 4===4 evaluates to true, whereas the expression 4==="4" evaluates to false. (The second expression returns false because no type conversions occur in an identity operation.)
!== | Nonidentity. Tests whether two values are unequal or of different data types, or unequal and of different data types. This operation returns true unless both values are of the same type and have the same value. For example, the expression 4!==4 evaluates to false, while the expressions 4!==5, (4!=="5"), and 4!=="4" all evaluate to true. (No type conversions occur in a nonidentity operation.)

if... Statements

Now that you've seen how to use Boolean comparisons, let's put them to work in some conditional statements. The most basic type of conditional statement is the if... statement, commonly known in many languages as an if...then statement. This statement specifies that if a condition is met (if a value is true), then an action should occur. If the value is not true, the action does not take place. An if... statement begins with the term if followed first by a Boolean expression in parentheses and then by a set of actions enclosed in curly braces. The following line of code demonstrates a basic if... statement:

if(x==4){alert("x is equal to four")}

This statement first tests to see whether x is equal to 4. If it is, the code produces an Alert dialog box containing the text x is equal to four.

An expanded version of the if... statement is the if...else statement. This statement specifies that if a condition is met, then an action should occur; otherwise (else), a different action should occur. Code Listing 9-3 expands on Code Listing 9-2 and shows how an if...else statement can be used to check data for errors. Figure 9-3 shows what happens if you enter a letter instead of a number in the text area.

Code Listing 9-3.

<HTML>
<HEAD>
<TITLE>Listing 9-3</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function rndNum(maxNum){
  num=Math.random()
  num=num*maxNum
  num=Math.ceil(num)
  return num
}
function tellUser(specifiedNum){
  if (isNaN(specifiedNum)){
    alert("Please enter only numbers.")
  }
  else {
    alert(rndNum(specifiedNum))
  }
}
</SCRIPT>
</HEAD>
<BODY>

Type a number in the area below, and then click Calculate.<BR>
The page will generate a random number between 1 and the
number you entered.<BR>

<FORM>
<TEXTAREA NAME="TextNum">10</TEXTAREA>
<BR>
<INPUT TYPE="button" VALUE="Calculate"
       onclick="tellUser(TextNum.value)">
</FORM>
</BODY>
</HTML>

Click to view at full size.

Figure 9-3. Checking data for errors.

The tellUser function first uses the isNaN method to test the value that is passed to it. (This method returns true if the value is not a number and false if the value is a number.) If the value is not a number, the tellUser function advises the user to enter only numbers. Otherwise, if the value passed is a number, tellUser calls the rndNum function and operates the same as Code Listing 9-2.

The Conditional Operator

The conditional operator allows what is essentially a compressed if...else statement. The following line of code shows the conditional operator in use:

alert(x>4?"x is greater than 4":"x is not greater than 4")

A conditional statement begins with a Boolean test, followed by a question mark. It then indicates the value that should result if the test is true, separated by a colon from the value that should result if the test is false. In the alert example shown here, the conditional statement is the code inside the parentheses. This statement will return x is greater than 4 or x is not greater than 4 depending on whether the test x>4 is true or false. We could have written this code as an if...else statement as follows:

if (x>4){alert("x is greater than 4")}
else{alert("x is not greater than 4")}

switch Statements

A switch statement is like an expanded if...else statement. It lets you specify different actions for different values of an expression. (In some other languages, a switch statement is called a case statement.) Code Listing 9-4 uses a switch statement; see Figure 9-4 for an example of the page that results.

Code Listing 9-4.

<HTML>
<HEAD>
<TITLE>Listing 9-4</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function testColor(givenColor){
  givenColor=givenColor.toLowerCase()

  switch (givenColor){
    case "blue" : alert("That is my favorite color!") ; break
    case "green": alert("Yuck, I don't like green.") ; break
    case "red"  : {
      alert("I don't like red as much as blue.")
      break
    }
    default:alert("I like blue the best.") ; break
  }
}
</SCRIPT>
</HEAD>
<BODY>
What is your favorite color?<BR>

<FORM>
  <TEXTAREA NAME="TextArea1">Blue</TEXTAREA><BR>
  <INPUT TYPE="button" VALUE="Test" onclick="testColor(TextArea1.value)">
</FORM>
</BODY>
</HTML>

Click to view at full size.

Figure 9-4. Using a switch statement.

You can think of a switch statement as a list of different sets of actions that should be taken in different circumstances. The switch statement begins with the word switch followed by the expression being tested, surrounded by parentheses. After this, curly braces define the beginning and end of the list of actions to take in different cases. These actions take the form of the word case followed by a potential value of the expression, a colon, and then the desired action. You can also specify an optional default action that will take place when the value does not match any of the previously specified cases.

In Code Listing 9-4, when the user types the name of a color into the text area and clicks the Test button, the testColor function is called. This function converts the text in the text area to lowercase, which allows us to compare it to a set of values. (Without this conversion, it is more difficult to test the value entered by the user; the string blue is not equivalent to Blue, for instance.) The switch statement then begins. It tests the givenColor variable and specifies the action to be taken if the value of the variable is equal to blue, red, or green as well as a default action if the value is anything else. Each case can have multiple actions, each written on separate lines or separated with semicolons. The final action of each case should be a break statement, which marks the end of that case and prevents the actions specified for other cases in the switch statement from executing. Support for the switch statement is relatively recent; it is not supported in version 3 of Navigator or Internet Explorer. (Technically, it is not version 3 of Internet Explorer that does not support the switch statement. Instead it is the version of the JScript engine that shipped with it. New versions of the JScript engine can be downloaded from http://msdn.microsoft.com/scripting and used in versions 3 and later of Internet Explorer.)


Loops

By using loops, you can cause actions to be repeated. Loops can be useful in reducing the amount of code you need to write. In the next sections, we'll take a quick look at four kinds of loops before demonstrating them in Code Listing 9-5.

for Loops

One of the most common types of loop is the for loop, typically used to perform actions a set number of times. The following line of code demonstrates a basic for loop that displays 10 successive Alert dialog boxes:

for (var i=1;i<=10;i++){alert("This is alert number "+i)}

A for loop begins with the word for. The code that follows, in parentheses, includes the initialization, which specifies a counting variable and gives it an initial value. The initialization is followed by a semicolon and a test, which is a Boolean expression. If the test evaluates to true, the actions specified by the code in the curly braces will be executed; if the test evaluates to false, the code will not run. Thus, in the example shown here, the loop will be run as long as i is less than or equal to 10. The next part of the code includes a semicolon and an increment, which specifies how the counting value should change. We used i++, which adds 1 to i. Finally the code specifies the actions to be taken, enclosed in braces.

for...in Loops

You can use a for...in loop to step through all of an object's properties or all of the indexes in an array. For example, the following line of code will print each index of an array named myArray on a new line:

for (i in myArray){document.write(myArray[i]+"<BR>")}

On the CD, you will find a useful Web page called ObjInfo.htm in the Tools folder. This page takes an object specified by the user and uses a for...in loop to step through and display all of its properties. Figure 9-5 shows the information ObjInfo.htm displays about the document object.

Click to view at full size.

Figure 9-5. Information about the document object.

while Loops

A basic while loop specifies an action to be taken as long as a Boolean test returns true. Like a for loop, a while loop can be used to count, and you can also use it to test the values of data. This type of loop consists of the word while followed first by a Boolean test and then by the code specifying the actions that should occur. The following line of code demonstrates a basic while loop that displays 10 successive Alert dialog boxes (assuming that the variable i starts out with a value of 1):

while(i<=10){alert("This is alert number "+i);i++}

do...while Loops

A variation of the while loop, called a do...while loop, performs a set of actions once and then repeats them as long as a condition is met. Its primary difference from the other loops is that the action is always performed at least once, because the test occurs at the end of the loop. The following code snippet will cause one alert to be displayed, even though 5 is not less than or equal to 3.

i=5;
do{alert("This is alert number "+i);i++}while(i<=3)

If i had been set equal to 1, three alert boxes would have resulted.

Code Listing 9-5 shows the different loops in use. In this sample, the user is asked to enter five numbers, which are then displayed on screen. Let's examine each part of this sample. First we declared a new array and filled it with three items of data by using a for loop. (Because arrays are zero-ordered, we started at 0 and counted to 2 rather than starting at 1 and counting to 3.) Next we used a for...in loop to allow the user to guess each number in the array.

A while loop determines whether the user's guess is correct; if it is not, the program asks the user to try again. This continues until the user guesses correctly or clicks cancel. Next we used an if... statement to test whether the user clicked cancel to quit. If the user clicks cancel, an if...else statement is used to present a dialog box that asks the user whether he or she wants to quit entirely or go on to the next number. If the user chooses to quit, the break expression is used. The break expression can be used to exit all types of loops. If the user chooses to move on to the next number, the specified action is continue, which goes on to the next iteration of our for...in loop and thus continues to the next number. Finally, after the program is finished, the user sees a goodbye message in the browser window.

Code Listing 9-5.

<HTML>
<HEAD>
<TITLE>Listing 9-5</TITLE>
<SCRIPT LANGUAGE="JavaScript">
var numArray=new Array
for (var i=0;i<=2;i++){
  numArray[i]=Math.ceil(Math.random()*4)
}

alert("You will be asked to guess three numbers I have picked.")

for (j in numArray){
  guess=prompt("Guess between 1 and 4. Cancel will exit.","")

  while((guess!=numArray[j])&&(guess!=null)){
    guess=prompt("Nope! Try again or type 0 to quit.","")
  }

  if (guess==null){
    if(confirm("OK to quit, Cancel to guess the next number.")){
      break
    }
    else{continue}
  }

  alert("That's right!")
}

alert("Goodbye!")
</SCRIPT>
</HEAD>
</HTML>

When using any type of loop, you should be careful to ensure that you do not end up in an infinite loop. An infinite loop is one that is never exited. This can occur in many different ways and is more common with while loops than for loops. For example, the following snippet of code will result in an infinite loop.

i=0
while(i<=10){alert("This is alert number "+i);a++}

The counter variable i is never incremented; the variable a is incremented instead. Thus, i is always less than 10, and the loop is never exited.

NOTE
Caution: Do not execute this line of code in a browser. If you do, your browser is likely to hang. If this does occur (and you are running Microsoft Windows 95, Windows 98, or Microsoft Windows NT), press the Ctrl, Alt, and Del keys simultaneously. This should bring up a window that will allow you to select the browser that is not responding and choose End Task, which will stop the program.

Internet Explorer 5 also supports new features called Conditional Compilation Conditional Comments. Because they can be helpful for writing cross browser code, they are covered in Chapter 23.

The past several chapters have focused on the basics of scripting. The next chapter will take a look at ways to trap errors and debug your code.


Chapter 10 -- Debugging and Error Handling

 Chapter 10

Debugging and Error Handling

In the previous several chapters, we have focused on writing script using basic scripting techniques such as conditional statements, functions, and data type manipulation. If you have been trying to incorporate such code into your own Web pages, you may have noticed errors happening on occasion. In this chapter, we'll discuss general code debugging practices and techniques, as well as ways to write code that traps scripting errors automatically.


Types of Errors

There are many different types of errors you can make on a Web page. The most common errors tend to fit into the following groups:

  • Syntax errors, in which the rules of the language are not followed. Examples include not following a JScript function name with parentheses or closing a string with a double quote that was opened with a single quote. Syntax errors are usually fairly easy to track down since they usually cause a descriptive error message to appear.

  • Unexpected state errors, in which code encounters a situation that it has not been written to deal with gracefully. Examples include a function that expects numbers only but is passed a string, or a block of code expecting an object or frame to be loaded that has not yet completely loaded. Tracking down these errors ranges in difficulty, depending on the exact error.

  • Logic errors, in which valid code is used to do something undesired. Examples include unwitting use of the incorrect formula for calculating tax, or using the incorrect operator (+ instead of -, or = instead of = =) in a math statement. These can be the most difficult types of code errors to debug, as they do not tend to result in overt error messages.

Next we'll look at some common debugging techniques.


Debugging

Because no programmer is perfect, part of all development involves testing and debugging code. There are thousands of techniques for debugging code. This section will cover some of our favorite techniques, which range from general bug prevention practices to the use of specific debugging tools such as Microsoft Visual Interdev.

Error Prevention and Tracking

There is an old adage that the best offense is a good defense. In the world of coding, the best way to have error-free code is to prevent errors in the first place. Following are some useful techniques for avoiding errors and finding them once they occur.

  • Name variables appropriately. It is easy to access the wrong variable if you use names like S11 and S12, instead of strFirstName and strLastName.

  • Use formatting to make your code easier to read. Indenting code can help you see which code is part of a loop or which <TD> tags belong with which rows.

  • Create small, reusable functions. Small functions make it easier to isolate problems, and the more reusable code you use, the less new code you will have to test.

  • Use descriptive comments liberally. Comments help explain what the programmer intended each part of the code to do.

  • When possible, place script in the head of a Web page. This ensures that the code is loaded before any of the objects in the body. So, for example, functions and event-handling code are loaded before objects in the body that might call them.

  • Anticipate and code for unusual or unexpected states when writing your code. For example, if code from one frame calls on an object in another frame, test to make sure the target frame is loaded before trying to access its object. Such defensive coding can greatly increase stability.

  • Include error-handling code that prevents the user from ever realizing an error occurred. Such techniques will be covered later in the chapter.

  • Use tools that help you write clean code. Editors like Microsoft Visual Interdev and Allaire HomeSite will color-code your script, making different types of tags different colors and coloring everything between quotes. This can help you find common mistakes such as forgetting to end a tag with an angle bracket or omitting a quote or curly bracket in script. These tools also can automatically handle indenting and can generate code for common functions. Visual Interdev and Microsoft Script Debugger contain debugging features to help track down problems. Tools are described in more detail later in the chapter.

  • Make sure you are given as much error information as the browser can supply. Microsoft Internet Explorer 5 supports Developer mode, an option that displays script error messages on screen (described in the Note on the next page). Previous versions of Internet Explorer automatically displayed a lot of error information on screen. Netscape provides the Communicator Console for debugging information. It can be displayed by typing javascript: into the Location field in Navigator.

  • Use comments to help isolate problem code. If you think a line of script is causing an error, comment it out by inserting two forward slashes at the beginning of the line. Test problematic HTML by surrounding it with HTML comment tags (<!-- and -->).

  • Use techniques to track the values of variables and the state of different objects as the script is processed. These will be discussed next.

NOTE
Error messages are presented differently in different browsers. Internet Explorer 5 alerts the user that an error has occurred by displaying a message in the status bar at the bottom of the window. If the user double-clicks on the error notification in the status bar, the full error window appears. In some browsers, the error immediately displays on screen in a dialog box. Internet Explorer 5 can be configured to do this by checking the "Always display this message when a page contains errors" option in any error dialog box, or by checking the "Display a notification about every script error" option in the Tools menu under Internet Options/Advanced. This configuration is known as the "Developer mode" of error display and is highly recommended.

Visible Variables and Run-Time Coding

When working with code, it is often useful to know the values of certain variables or the state of a particular object. It can also be useful to create and run code after the page has been loaded. Code Listing 10-1 demonstrates several ways to accomplish these tasks. Figure 10-1 displays the results.

Code Listing 10-1.

<HTML>
<HEAD>
<TITLE>Listing 10-1</TITLE>
<SCRIPT LANGUAGE="JavaScript">
  function doIt(){
    a=10
    window.status=("a="+a)
    b=20
    alert("b="+b)
    c=a+b
  }
</SCRIPT>
</HEAD>
<BODY onload="doIt()">
<FORM NAME="frmDbg" onsubmit="eval(this.sDbg.value);return false">
  <INPUT TYPE="text" NAME="sDbg" SIZE="50">
  <INPUT TYPE="button" onclick="eval(frmDbg.sDbg.value)" VALUE="Run Code">
</FORM>
</BODY>
</HTML>

There are many ways to determine the status of different components of your code. One technique is to display information about the component in the Alert dialog box or in the Status bar at the bottom of the browser window. To change the Status bar contents, simply set a value for window.status. If you are using Internet Explorer version 4 or later as your test platform, you can also create a named <SPAN> tag and then change the innerHTML property of the span to display the error in the document itself.

Click to view at full size.

Figure 10-1. Several ways to debug.

Typically, it is useful to distinguish debugging code from the surrounding program code so that you don't forget to remove it before finalizing your development. An easy way to make debugging code stand out from other code is to not indent it. A more sophisticated method is to have a "debugging mode" for your page. For example, a variable named debug can be set to true or false. Conditional loops are set up around all of the debugging code that test the debug variable and run the debugging code only if debug is set to true.

A second technique in Code Listing 10-1 uses the text field. Any code that is typed into the text field will be evaluated when you press the Enter key or click the Run Code button. Use this technique when you do not know ahead of time what type of information you will be interested in once the page has loaded. Any valid JScript can be typed into the field for evaluation. For example, if you enter alert(window.location), an Alert dialog box containing the path to the current document will be displayed. If you enter alert(window.navigator.userAgent), information about the browser in use will be displayed.

Script Debugging Tools

Tools such as Script Debugger, Visual Interdev, and Netscape JavaScript Debugger are designed specifically to debug and analyze scripting code. Script Debugger is free and available with extensive documentation from msdn.microsoft.com/scripting. Script Debugger provides debug information for pages created with JScript, VBScript, and Java applications. It enables you to

  • Step through the script line by line or set break points to pause the script

  • Display and change the values of script variables and object properties

  • Debug Active Server Pages on servers running Microsoft Internet Information Services Web server

Script Debugger requires the developer's workstation to have installed Internet Explorer version 3.02 or later. Once Script Debugger is installed, it can be accessed from the View menu inside Internet Explorer or automatically launched from within script by using the keyword "debugger." A major limitation of Script Debugger is its inability to edit and debug the script within the same window.

Netscape JavaScript Debugger is a somewhat similar product. It can be found at http://developer.netscape.com/software.

Visual Interdev is a powerful development environment for rapidly creating Web applications. It is an excellent tool for creating both standard Web pages and database-driven server-side applications. Visual Interdev has built-in debugging and page analysis tools. It incorporates all of the features of Script Debugger and includes such additional features as

  • Comprehensive server- and client-side debugging tools for stepping through code and watching variables

  • A window that displays all attributes for a selected HTML tag

  • Integrated database tools that make creating database-driven applications easy

  • WYSIWYG editing

  • Tree control representation of the page and scripts on the page

  • Easy drag-and-drop use of ActiveX controls

We highly recommend Visual Interdev for anyone creating applications with both server- and client-side components, especially those involving database connectivity.


Error Handling

As programming languages like VBScript and JavaScript have become more complex and sophisticated, so too have the errors that programmers make when writing code. With error handling, however, you can write code into your script that traps errors and solves them internally or alerts the end user to the error with an informative message. For example, if a script calls an ActiveX control or Java applet that is not fully loaded, it would normally result in an error dialog being displayed to the user. This can be circumvented with error-handling code.

The onerror Event Handler

Handling the onerror event is one way to trap and work around scripting code errors. When an error occurs in a specified object, an onerror event is fired and the user is alerted. Objects that support onerror include the IMG, LINK, OBJECT, SCRIPT, STYLE, and, most useful of all, window objects. Netscape Navigator versions 3 and later and Internet Explorer versions 4 and later support onerror. Code Listing 10-2 shows a basic use of the onerror event. Figures 10-2 and 10-3 display the results.

Code Listing 10-2.

<HTML>
<HEAD>
<TITLE>Listing 10-2</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function jHandleImageError(oImg){
  alert(`Could not load the image `+oImg.name+". Loading alternate.")
  oImg.src=`unavailable.gif'
}
</SCRIPT>
</HEAD>
<BODY>
This image does not use an error handler.
<IMG SRC="one.gif" NAME="ImageOne"><BR>
This image does use an error handler.
<IMG SRC="two.gif" NAME="ImageTwo" onerror="jHandleImageError(this)">
</BODY>
</HTML>

Click to view at full size.

Figure 10-2. A programmed error message appears...

Click to view at full size.

Figure 10-3. ...and then an alternate image is loaded.

When Code Listing 10-2 is run, it first attempts to load the images one.gif and two.gif, which can't be found, because neither image is included on the companion CD. The ImageOne object cannot load the one.gif graphic and fires the onerror event. No action is taken because there is no error handler on this image, so the user is left with only a missing graphic symbol. When the browser tries to load two.gif, the onerror event fires again. This time an in-line onerror event handler captures the error. The event handler calls a function that alerts the user with an error message and then loads an alternate graphic. The in-line event handler can also be used on OBJECT and SCRIPT elements to point to alternate resources when the browser is unable to load a file.

In the window object, onerror works to trap general errors. Code Listing 10-3 shows what happens when a page of script without error handling calls an object that does not exist.

Code Listing 10-3.

<HTML>
<HEAD>
<TITLE>Listing 10-3</TITLE>
</HEAD>
<BODY>
Clicking this button calls a nonexistent object.
<FORM><INPUT TYPE="button" VALUE="Click Me" onclick="FakeO.use()"></FORM>
</BODY>
</HTML>

Click to view at full size.

Figure 10-4. The error dialog from Internet Explorer when Code Listing 10-3 is run.

When the user clicks the button, its onclick event handler attempts to use a method from an object that doesn't exist. This results in a standard undefined object error message being presented to the user, shown in Figure 10-4. The next code listing traps the error. The results are shown in Figure 10-5.

Code Listing 10-4.

<HTML>
<HEAD>
<TITLE>Listing 10-4</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function errorHandler(msg,url,line) {
  strPrompt=("Captured error \n"+msg+"\n on line "+line+" in "+url+".")
  strPrompt+=("\nCancel display of standard error message?")
  if (confirm(strPrompt)){return true}
  else {return false}
}
window.onerror=errorHandler;
</SCRIPT>
</HEAD>
<BODY>
Clicking this button calls a non-existent object.
<FORM><INPUT TYPE="button" VALUE="Click Me" onclick="FakeO.use()"></FORM>
</BODY>
</HTML>

Click to view at full size.

Figure 10-5. Code Listing 10-4 handles the error.

When Code Listing 10-4 is first loaded, an errorHandler function is added to the window object with the statement window.onerror=errorHandler. This statement means that whenever the window object fires the onerror event, the errorHandler function will be called. The errorHandler function takes three parameters that contain information about the error. The msg parameter contains the text of the error message, url provides the URL of the page in which the error occurred, and line provides the line number of the script that caused the error. These parameters are available only from an onerror event handler on the window object, not on other objects, such as images. Using these parameters, the function then formats and presents an error message to the user, along with the option to cancel the default error message. If the errorHandler function returns the value true, the window object will not display an additional error message. If false or no value is returned, the regular error message will be displayed. The errorHandler function can also prevent any error message from being displayed with a return true statement, or by setting the window.event.returnValue property to true.

In addition to the in-line onerror event handler demonstrated in Code Listing 10-2 and the window.onerror handler shown in Code Listing 10-4, you can create a specific script block containing the error-handling code, as follows:

    <SCRIPT LANGUAGE="JavaScript" FOR="window" EVENT="onerror(msg,url,line)">
    [...script commands...]
    </SCRIPT>

This type of script block works only in Internet Explorer, not in current versions of Netscape Navigator.

The try...catch and throw Statements

A new mechanism for error handling that is currently supported in the JScript 5 script engine, which comes with Internet Explorer 5 and can be used in IIS and earlier versions of Internet Explorer, is the try...catch statement. It is very useful when running script on the server, where there is no window object. It is also handy because different error-handling code can be placed around different problem areas. Code Listing 10-5 shows a try...catch statement. Figure 10-6 displays the results.

Code Listing 10-5.

<HTML>
<HEAD>
<TITLE>Listing 10-5</TITLE>
<SCRIPT LANGUAGE="JavaScript">
try {
  document.write("This statement works.")
  document.write(fakeO.use())
  document.write("This statement does not work.")
}
catch (e) {
  strError=("An error occurred. The error number was "+e.number+". ")
  strError+=("The error message was \""+e.description+"\"")
  alert(strError)
}
</SCRIPT>
</HEAD>
<BODY>
</BODY>
</HTML>

Click to view at full size.

Figure 10-6. Code Listing 10-5 handles an error with a try...catch statement.

As the page is being loaded, the script block is run. As you can see, the script begins with a try block, which contains a series of statements that the browser attempts to run. If any of the statements results in an error, the error is trapped and passed to the subsequent catch block, which constructs and displays an error message.

The first statement in the try block is a document.write method that has no errors and is executed successfully. The second line calls on an object and a method that do not exist. This causes an error, and so the catch block is called, which constructs and then displays an error message.

The catch statement is automatically passed a parameter that contains an error object. This object has two properties, number and description. Each type of script error is assigned a unique error number. The number property can be tested and can cause different effects depending on the error. The description property contains a textual description of the error.

The try...catch statement is especially useful on the server side, where there is no window object to trap errors. It can also be used to set default values. For example, the following statement will assign the value of b to a, unless there are any problems doing so (for instance, if b doesn't exist), in which case a will be assigned the value 5 instead.

try {a=b}
catch {a=5}

The throw statement can be used to pass a specific error message to a catch statement. It can also be used to pass an error to a higher-level error handler in the case of nested try...catch statements. Code Listing 10-6 demonstrates both of these techniques.

Code Listing 10-6.

<HTML>
<HEAD>
<TITLE>Listing 10-6</TITLE>
<SCRIPT LANGUAGE="JavaScript">
processedSuccessfully=false
sProb=""
while (!processedSuccessfully){
  try {
    try {
      intInput=prompt(sProb+"Enter a number to divide into 100.",4)
      // send specific error to inner handler
      if (isNaN(intInput)){throw "NaN"}
      if (intInput==0){throw "div0"}
      x=(100/intInput)
      sOutput=("100 divided by "+intInput+" equals "+x)
      processedSuccessfully=true
    }
    catch(e) {
      sErr="Handled in inner handler. "
      if (e == "NaN"){
        sProb=(sErr+"You did not enter a valid number.\n")
      }
      // send other errors to outer handler
      else{throw e}
    }
  }
  catch(e) {
    sErr="Handled in outer handler. "
    if (e=="div0"){
      sProb=(sErr+"You entered 0, which cannot be a divisor.\n")
    }
  else{sOutput=(sErr+e.description);break}
  }
}
document.write(sOutput)
</SCRIPT>
</HEAD>
<BODY>
</BODY>
</HTML>

Code Listing 10-6 begins by prompting the user for a number. The code uses a while loop that continues to prompt the user until a number is entered that meets the code's requirements, or until a break statement is called that takes the user out of the while loop. When a valid number is entered, the code divides the number into 100 and adds the result to the sOutput variable, which is then written to the browser window.

There are, however, several predictable user input errors that could upset this process. A user could, for instance, enter 0, which does not divide meaningfully into 100, or the user could enter text instead of a number. Additionally, some type of unexpected error could occur. As a result, we've utilized the try, catch, and throw statements in our code to test for, capture, and report these types of errors.

The inner try statement tests whether the user entered data that is not a number and whether the number entered is 0. If either of these situations occur, the throw statement is used to send information about the error to the catch statement, which creates and displays a specific error message. If any other errors occur, they are automatically sent to the catch statement, as usual.

If the user enters a non-number (text or symbol) string, the inner catch statement detects this error and adds it to the sProb variable, which is appended to the prompt when the user is next asked for a number. If the user enters 0, the error is thrown to the outer catch statement, which also modifies the sProb variable. Any other errors are described in the sOutput variable, after which the break statement is used to exit the while loop. The document.write method then describes these errors on the screen. To cause such a problem, copy the listing to your hard drive and comment out the line that reads x=(100/intInput). This will cause an `x' is undefined error message to display.

More About the number Property

The JScript scripting engine inside Internet Explorer can return the errors shown in Table 10-1. This table does not list errors returned by objects that are external to the scripting engine (like the Media Player and other ActiveX controls) and that can return their own custom errors.

Table 10-1

Error Number | Error Description
5 | Invalid procedure call or argument
6 | Overflow
7 | Out of memory
9 | Subscript out of range
10 | This array is fixed or temporarily locked.
11 | Division by zero
13 | Type mismatch
14 | Out of string space
17 | Can't perform requested operation
28 | Out of stack space
35 | Sub or Function not defined
48 | Error in loading DLL
51 | Internal error
52 | Bad file name or number
53 | File not found
54 | Bad file mode
55 | File already open
57 | Device I/O error
58 | File already exists
61 | Disk full
62 | Input past end of file
67 | Too many files
68 | Device unavailable
70 | Permission denied
71 | Disk not ready
74 | Can't rename with different drive
75 | Path/File access error
76 | Path not found
91 | Object variable or With block variable not set
92 | For loop not initialized
93 | Invalid pattern string
94 | Invalid use of Null
322 | Can't create necessary temporary file
424 | Object required
429 | Automation server can't create object
430 | Class doesn't support Automation
432 | File name or class name not found during Automation operation
438 | Object doesn't support property or method <item>
440 | Automation error
445 | Object doesn't support this action
446 | Object doesn't support named arguments
447 | Object doesn't support current locale setting
448 | Named argument not found
449 | Argument not optional
450 | Wrong number of arguments or invalid property assignment
451 | Object not a collection
453 | Specified DLL function not found
458 | Variable uses an Automation type not supported in JScript
501 | Cannot assign to variable
502 | Object not safe for scripting
503 | Object not safe for initializing
504 | Object not safe for creating
5000 | Cannot assign to `this'
5001 | <Item> is not a number; Number expected
5002 | <Item> is not a function; Function expected
5003 | Cannot assign to a function result
5004 | <Item> is not an indexable object; Cannot index object
5005 | <Item> is not a string; String expected
5006 | <Item> is not a date object; Date object expected
5007 | <Item> is not an object; Object expected
5008 | Cannot assign to <item>; Illegal assignment
5009 | <Item> is undefined; Undefined identifier
5010 | <Item> is not a boolean; Boolean expected
5011 | Can't execute code from a freed script
5012 | Cannot delete <item>; Object member expected
5013 | <Item> is not a VBArray; VBArray expected
5014 | <Item> is not a JScript object; JScript object expected
5015 | <Item> is not an enumerator object; Enumerator object expected
5016 | <Item> is not a regular expression object; regular expression object expected
5017 | Syntax error in regular expression
5018 | Unexpected quantifier
5019 | Expected `]' in regular expression
5020 | Expected `)' in regular expression
5021 | Invalid range in character set

You will notice that the numbers reported in this table differ substantially from those reported by the actual number property. Code Listing 10-7 demonstrates how to convert the number reported in the number property to the one shown in the chart above. Figure 10-7 displays the results.

Code Listing 10-7.

<HTML>
<HEAD>
<TITLE>Listing 10-7</TITLE>
<SCRIPT LANGUAGE="JavaScript">
try {
  x=y
}
catch (e) {
  strError=("An error occurred. error.number was "+e.number+"\n")
  strError+=("Convert this and get "+(e.number&0xFFFF)+"\n")
  strError+=("The error message was \""+e.description+"\"")
  alert(strError)
}
</SCRIPT>
</HEAD>
</HTML>

Figure 10-7. Code Listing 10-7 converts an error to the value shown in Table 10-1.

The technical explanation for this is as follows. The numbers in Table 10-1 represent only the lower order bits of the number in e.number. The second line that references e.number performs a bitwise AND operation with the & operator to retrieve only the lower order bits. This is also known as performing a bit mask. You can find out more about the & operator at msdn.microsoft.com/scripting, where you can also find more information about handling errors.

So far, we've looked at some functions and features of HTML and scripting. Part 3 introduces Cascading Style Sheets (CSS), a technology that has been around since Internet Explorer 3 but that has been greatly expanded since then. CSS gives you extensive control over the appearance of your pages and makes it easy to give an entire Web site a consistent look and feel.


Chapter 11 -- Introduction to Cascading Style Sheets

 Chapter 11

Introduction to Cascading Style Sheets

In the early days of the Web, the number of HTML tags exploded. Different browsers supported their own proprietary tags, and no one browser supported all tags. To format text with proprietary tags, you had to include them within the content of the document itself, usually in place of more widely supported tags. This tied the appearance (or style) of the content to the content itself, which led to a number of problems; most prominently, this meant that content formatted in one browser was not necessarily formatted in another, and changing the look and feel of a Web site required retagging all documents on the site.

The Cascading Style Sheets (CSS) specification was developed by the World Wide Web Consortium (W3C) to head off this trend and to provide a simple model that separates the style of a document from the content. A style sheet following this specification can be added to a Web page or site that specifies the appearance or style of all tags on the page or site. For example, a style sheet can be created that defines <H1> tags as bold 24-point Verdana type with a 1-centimeter white border and a red background. Changing this one definition can change the appearance of all <H1> tags on the site. With this separation, what previously required retagging the entire content of a document now can be done with a few simple tweaks to the document style. In addition, CSS allows an unprecedented level of control over the appearance and layout of Web-based documents. With CSS, you can alter everything from the size, style, and color of text to the spacing between letters and lines, the border and padding around elements, and the exact position of an object on the page.

Dynamic styles is Microsoft's implementation of CSS, used in Internet Explorer. It complies more closely with the Cascading Style Sheets level 1 (CSS1) and the more recent level 2 (CSS2) specifications than any other common browser. Although, in the strictest sense, dynamic styles refers to the Microsoft implementation of CSS, we (like the rest of the Web community) will use the terms "Cascading Style Sheets," "CSS," "styles," and "dynamic styles" interchangeably throughout this book.

While several browsers include some support for styles (including Internet Explorer 3 and Netscape Navigator versions 4 and later), Internet Explorer versions 4 and 5 currently offer the most extensive support. However, no browser implements the entire CSS2 specification, in part because CSS2 is designed to expand the concept of styles to apply to just about any medium, including audio. For information on the various CSS specifications as defined by the W3C, visit the W3C Web site at www.w3.org/Style/. These documents are well written, detailed but readable, and useful. Support for these specifications is becoming much more widespread. Netscape has pledged far greater support for Navigator 5, and versions 3.5 and later of Opera Software's Opera browser provide extensive support for CSS.

This chapter discusses two ways of applying styles: (1) using the STYLE attribute to apply styles to individual elements and (2) using style sheets to apply styles to a page or an entire Web site. A style sheet can be an external file linked to an HTML document, or it can be included in the document itself. The following sections explain the basic syntax for using styles in these ways. For information on applying styles through script, see Chapter 15.


In-Line Styles

An in-line style is a style applied to a particular tag on a Web page. You can apply an in-line style to any tag on a page by using the STYLE attribute. Like other attributes, STYLE affects only the tag that contains it, just as setting the WIDTH attribute for an image affects only that image. Therefore, in-line styles are most useful for precise control of a single element, rather than for large-scale changes to an entire page or site.

Let's look at a simple HTML document without styles, shown in Code Listing 11-1. You can see the document created by this code in Figure 11-1.

This listing uses the <SPAN> tag, which is especially handy when working with styles because it acts as a container for text without applying any formatting of its own. Thus, in the Web page created by Code Listing 11-1, the text between the opening <SPAN> tag and the closing </SPAN> tag will display like normal text, but it can be treated as one text chunk.

Code Listing 11-1.

<HTML>
<HEAD>
<TITLE>Listing 11-1</TITLE>
</HEAD>
<BODY>
<SPAN>This text is in a SPAN.</SPAN><BR>
This text is not in a SPAN.
</BODY>
</HTML>

Click to view at full size.

Figure 11-1. A simple HTML document without styles.

This code allows us to add an in-line style that changes the text in the SPAN element to boldface by using the font-weight attribute, as shown in Code Listing 11-2. You can see this change in Figure 11-2.

Code Listing 11-2.

<HTML>
<HEAD>
<TITLE>Listing 11-2</TITLE>
</HEAD>
<BODY>
<SPAN STYLE="font-weight: bold">
This text is in a SPAN.</SPAN><BR>
This text is not in a SPAN.
</BODY>
</HTML>

Click to view at full size.

Figure 11-2. An example of applying an in-line style.

Notice that the <SPAN> tag in Code Listing 11-2 now includes a STYLE attribute, which causes any text contained in the SPAN element to have the formatting specified by this attribute. Also notice the syntax of the STYLE attribute. STYLE is assigned a value enclosed in quotation marks. This value contains the style declaration. Here the name of a particular attribute (such as font-weight) is followed by a colon and the value assigned to that attribute. (The syntax used for style sheets differs slightly from the in-line style syntax described here, as you will see later in this chapter.)

You can have more than one style declaration in a STYLE attribute. For example, in Code Listing 11-3, we added the font-style attribute (set to italic) to our boldface font-weight attribute. Notice that both style declarations are in the same set of quotation marks and are separated by a semicolon. Figure 11-3 illustrates the use of these two styles.

If you are familiar with HTML, you will notice that the results of Code Listings 11-2 and 11-3 could have been achieved by using traditional HTML without dynamic styles. Although HTML does allow basic formatting such as the use of boldface and italics, dynamic styles offers finer control over a greater number of formatting and layout options, from fonts and exact page position to multimedia filters.

Code Listing 11-3.

<HTML>
<HEAD>
<TITLE>Listing 11-3</TITLE>
</HEAD>
<BODY>
<SPAN STYLE="font-weight: bold; font-style: italic">
This text is in a SPAN.</SPAN><BR>
This text is not in a SPAN.
</BODY>
</HTML>

Click to view at full size.

Figure 11-3. An example of using multiple in-line styles in the same tag.

So far, we have used styles to format individual elements. CSS also lets you control the formatting of a whole Web page or Web site when you use style sheets, as you'll see in the next section.


Style Sheets

A style sheet consists of one or more style definitions (also called style rules). A style sheet can be contained within a Web document or kept in a file outside the document. A style definition is made up of a selector followed by a declaration block, as shown in this example:

SPAN {font-weight: bold; font-style: italic}

The selector is simply the item to which the style will apply. In most cases, the selector is an HTML tag (although it can also be a global class, described later in this chapter). Selectors are designated by tag name only and omit the opening and closing angle brackets (< >) normally found in HTML. In the example above, SPAN is our selector, so all SPAN tags in our document will follow the rules specified in this style definition.

The declaration block follows the selector and is enclosed in curly braces. This block is a list of style declarations, separated by semicolons. Our example contains two style declarations: font-weight: bold and font-style: italic.

As it stands now, this style definition would have no effect on a Web page. To make style definitions work, you must include them as part of either a global style sheet or a linked (external) style sheet.

Global Style Sheets

A global (or embedded) style sheet is included as part of the HTML in a document. This type of style sheet defines its boundaries by the <STYLE> and </STYLE> tags and must be placed in the header region of the HTML document.

In Code Listing 11-4, we took the style definition from the preceding section and incorporated it into a global style sheet. As you can see in Figure 11-4, the output on the page is the same as when we used these properties in an in-line style (Figure 11-3, above). In this case, however, the style is defined separately, and it is applied to all <SPAN> tags in the document.

Code Listing 11-4.

<HTML>
<HEAD>
<TITLE>Listing 11-4</TITLE>
<STYLE>
  SPAN {font-weight: bold; font-style: italic}
</STYLE>
</HEAD>
<BODY>
<SPAN>This text is in a SPAN.</SPAN><BR>
This text is not in a SPAN.
</BODY>
</HTML>

Click to view at full size.

Figure 11-4. An example of using a global style sheet.

In Code Listing 11-5, we expanded our HTML file to demonstrate the "reusability" of a global style sheet. This listing contains more text than the previous examples. Some regions of text are enclosed within <SPAN> tags, and some are not. Because we have created a style definition for SPAN elements in a global style sheet, the formatting specified by this style definition is applied to all of the SPAN regions but not to the other (non-SPAN) regions. This difference is obvious in Figure 11-5.

Code Listing 11-5.

<HTML>
<HEAD>
<TITLE>Listing 11-5</TITLE>
<STYLE>
  SPAN {font-weight: bold; font-style: italic}
</STYLE>
</HEAD>
<BODY>
<SPAN>This text is in a SPAN.</SPAN><BR>
This text is not in a SPAN.<BR>
<SPAN>This text is in a SPAN. </SPAN><BR>
This text is not in a SPAN.<BR>
<SPAN>This text is in a SPAN. </SPAN><BR>
This text is not in a SPAN.<BR>
</BODY>
</HTML>

Click to view at full size.

Figure 11-5. Using a global style sheet that affects text in all SPAN elements.

Now let's add more style definitions to our style sheet. In Code Listing 11-6, we define the style for level 1 headings (<H1> tags) as 16-point boldface red text and the style for level 2 headings (<H2> tags) as 24-point italic green text. Figure 11-6 shows that the normal formatting for the SPAN, H1, and H2 elements in this document is overridden by our style sheet.

Code Listing 11-6.

<HTML>
<HEAD>
<TITLE>Listing 11-6</TITLE>
<STYLE>
  H1   {font-size: 16pt; font-weight: bold; color: red}
  H2   {font-style: italic; font-size: 24pt; color: green}
  SPAN {font-weight: bold; font-style: italic}
</STYLE>
</HEAD>
<BODY>
<SPAN>This text is in a SPAN.</SPAN>
<H1>This text is in an H1.</H1>
<H2>This text is in an H2.</H2>
</BODY>
</HTML>

Click to view at full size.

Figure 11-6. Using a global style sheet to change the styles of multiple elements.

If you want to alter further the appearance of any type of element in Code Listing 11-6, you can simply alter the style sheet. For example, if you change the H2 style definition to display text as blue, all H2 elements found in the document will reflect this change.

If you want a particular instance of an element to be formatted differently from what is specified in the global style sheet, you can override the style sheet by using an in-line style for that specific element. Code Listing 11-7 and Figure 11-7 provide an example. In Figure 11-7, the first H2 element in the document uses the style defined in the style sheet, but the second H2 element has an in-line style that overrides the font-size declaration specified in the global style sheet.

Code Listing 11-7.

<HTML>
<HEAD>
<TITLE>Listing 11-7</TITLE>
<STYLE>
  H1   {font-size: 16pt; font-weight: bold; color: red}
  H2   {font-style: italic; font-size: 24pt; color: green}
  SPAN {font-weight: bold; font-style: italic}
</STYLE>
</HEAD>
<BODY>
<SPAN>This text is in a SPAN.</SPAN>
<H1>This text is in an H1.</H1>
<H2>This text is in an H2.</H2>
<H2 STYLE="font-size: 36pt">This is modified H2 text.</H2>
</BODY>
</HTML>

Click to view at full size.

Figure 11-7. An example of an in-line style used to override a global style sheet.

Linked Style Sheets

The formatting flexibility described in the preceding sections does not end at the level of the single Web page; you can control styles across several pages or even across an entire Web site by using linked style sheets. A linked (or external) style sheet is simply a text file that includes style definitions; it is saved using the CSS filename extension. This file, which is external to the HTML file, can be referenced by (or linked to) an HTML document that uses the HTML <LINK> tag.

Let's demonstrate the use of a linked style sheet with the style definitions from Code Listing 11-7. First we need to set up the style sheet. To do this, we can use any text editor, such as the Notepad application that ships on Microsoft Windows platforms, to create a file containing the style definitions shown in the following code:

H1 {font-size: 16pt; font-weight: bold; color: red}
H2 {font-style: italic; font-size: 24pt; color: green}
SPAN {font-weight: bold; font-style: italic}

We then save this file with the name styles.css. (Note the filename extension when looking for the file on the companion CD.) Notice that a linked style sheet does not include the <STYLE> and </STYLE> tags that are necessary with embedded style sheets in HTML documents.

We can now create an HTML document containing a link to this external style sheet. The code for this document appears in Code Listing 11-8; the display it produces is shown in Figure 11-8.

Code Listing 11-8.

<HTML>
<HEAD>
<TITLE>Listing 11-8</TITLE>
<LINK HREF="styles.css" REL="STYLESHEET" TYPE="text/css">
</HEAD>
<BODY>
<SPAN>This text is in a SPAN.</SPAN>
<H1>This text is in an H1.</H1>
<H2>This text is in an H2.</H2>
<H2 STYLE="font-size: 36pt">This is modified H2 text.</H2>
</BODY>
</HTML>

Click to view at full size.

Figure 11-8. Sample text styled with a linked style sheet.

The <LINK> tag should be used only in the header region of the HTML document. The <LINK> tag contains an HREF attribute. As it does in an <IMG> tag, HREF specifies the location of the target file. The REL attribute specifies that this link is a reference to a style sheet, and the TYPE attribute specifies the type of style sheet. Currently, the only commonly supported type of style sheet is text/css.

A linked style sheet has the same effect on an HTML document as a global (embedded) style sheet has. Every element in an HTML document whose tag is defined in the styles.css file is displayed using the specified style.

Because it is not contained within any particular HTML file, one linked (external) style sheet can be linked to an unlimited number of documents. You could, for example, create a linked style sheet for an entire Web site and link every page to that one style sheet. This ability is tremendously useful when you are trying to maintain a consistent look and feel across a Web site. It is also handy when you want to change the overall appearance of a Web site because modifications of any style in the site's CSS file are reflected immediately across the whole site. You can also use multiple <LINK> tags in one document to link to any number of different style sheets. (This feature is not supported in Internet Explorer 3.) Furthermore, the @import command enables one style sheet to include another. Both global and linked style sheets can use this command. For example, we could modify the styles.css file to include another style sheet as follows.

@import: url(ie.css);
H1 {font-size: 16pt; font-weight: bold; color: red}
H2 {font-style: italic; font-size: 24pt; color: green}
SPAN {font-weight: bold; font-style: italic}

This will cause a second style sheet, named ie.css, found in the same folder as styles.css, to be loaded. As shown here, any @import rules must be placed at the beginning of the file, before style definitions. The colon and semicolon in the @import line are required. Netscape does not currently support the @import rule.


Grouping and Shorthand Properties

The style definitions in the preceding code listings have been written out in their full form. To ease authoring tasks and reduce the size of style sheets, the CSS1 specification supports a feature called grouping, which allows a set of comma-separated selectors to be given the same styles. For example, you might write these three separate style definitions:

H1 {font-size: 16pt; font-weight: bold; color: red}
H2 {font-size: 16pt; font-weight: bold; color: red}
H3 {font-size: 16pt; font-weight: bold; color: red}

By using grouping, the code can be shortened to the following:

H1, H2, H3 {font-size: 16pt; font-weight: bold; color: red}

You can also use shorthand properties (also known as composite properties) to "group" certain style attributes. Using shorthand properties allows you to set multiple similar attributes simultaneously. For example, consider a style definition that includes the font-weight, font-size, and font-family attributes:

H1 {font-weight: bold; font-size: 16pt; font-family: Verdana}

The same formatting can be accomplished with the font shorthand property as follows:

H1 {font: bold 16pt Verdana}

Within a shorthand property, the individual attributes must be listed in a specific order. In other words, the slightly different code

H1 {font: 16pt bold Verdana}

will not yield the results you might expect because the font-size and font-weight attributes are reversed.

A variety of other shorthand properties exist, such as border, margin, and padding. You can find more information about the use of shorthand properties in CSS, including the specified order of attributes, in Chapters 12 and 13, as well as on the SBN Workshop Web site and on the CD that accompanies this book. On the CD, see Workshop (References); DHTML, HTML & CSS; CSS; CSS Attributes Reference. To get to the online version, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm , or open the file named MSDN_OL.htm on the companion CD, and choose CSS Attributes.


Inheritance

On almost every Web page, you can find HTML elements that contain other elements. As you've learned in earlier chapters, these embedded elements are commonly known as nested elements or child objects. In Code Listing 11-9, for example, a B element is nested inside the SPAN element. Figure 11-9 shows the resulting boldface word that appears within the text of the SPAN element.

Code Listing 11-9.

<HTML>
<HEAD>
<TITLE>Listing 11-9</TITLE>
</HEAD>
<BODY>
<SPAN>This is some <B>bolded</B> text in a SPAN.</SPAN>
</BODY>
</HTML>

Click to view at full size.

Figure 11-9. An example of a nested element.

Dynamic styles supports a mechanism called inheritance, in which the formatting of an outer, or parent, element (the SPAN element in Code Listing 11-9) is used as the basis for the formatting of the child object (the B element in Code Listing 11-9) nested within. Any additional or different formatting specified in the child object is applied to that nested element in addition to the inherited formatting. As an example, in Code Listing 11-10 we added a style sheet to the preceding code that declares a style for the SPAN and B elements. Figure 11-10 shows how the browser displays this page.

Code Listing 11-10.

<HTML>
<HEAD>
<TITLE>Listing 11-10</TITLE>
<STYLE>
  SPAN {font-size: 16pt; font-style: italic; color: red}
  B {font-size: 24pt}
</STYLE>
</HEAD>
<BODY>
<SPAN>This is some <B>bolded</B> text in a SPAN.</SPAN>
</BODY>
</HTML>

Click to view at full size.

Figure 11-10. An example of style inheritance.

In Figure 11-10, all the text within the SPAN element is 16-point, italic, and red. Because the B element is contained within the SPAN element, it inherits these same styles. However, it also adds to the mix its own boldface formatting and the 24-point font size declared in the global style sheet, making the text it contains 24-point, italic, red, and boldface.

Inheritance allows you to set default style definitions that will apply to all elements in a document. To do this, you simply set up a style sheet with style definitions for the BODY element of the document. Because BODY is the parent element of all the elements on the page, they will all inherit the style definitions you assign to the BODY element.

NOTE
One major exception to the inheritance system is that, in some browsers, tables do not inherit many attributes from the BODY element. You can work around this anomaly by adding a style declaration for the TABLE and TD elements.


Classes

CSS supports the creation of classes. Put simply, a class is a variation of an existing element. For example, suppose you want to use the <B> tag throughout your document, but you want slight variations depending on where each tag is used. As demonstrated in Code Listing 11-11, you can create classes of B elements that have the style variations you want. B elements normally appear in boldface black type. A class simply adds its own formatting to the tag. Thus, in our example, every B element remains boldface, but the class modifies the font size of specific B elements, as indicated in Figure 11-11.

Code Listing 11-11.

<HTML>
<HEAD>
<TITLE>Listing 11-11</TITLE>
<STYLE>
  B.large {font-size: 24pt}
  B.small {font-size: 8pt}
</STYLE>
</HEAD>
<BODY>
<B>This is a standard B.</B>
<B CLASS="small">This uses the small class.</B>
<B CLASS="large">This uses the large class.</B>
</BODY>
</HTML>

Click to view at full size.

Figure 11-11. Only the font size is changed by the B classes.

A class is defined by a selector name followed by a period and the class name (B.large, for instance). A value is then assigned to the class, using a statement enclosed in curly braces. No current browser allows more than one class level per tag—that is, the class B.large.bold is not allowed. You apply a class to an element with the CLASS attribute, as seen in the <B> tags in Code Listing 11-11.

You can create a global class that is usable by all elements if you do not specify a particular tag as a selector. Global classes are a powerful feature because they can be used for any tag on a page, as shown in Code Listing 11-12. Figure 11-12 shows the results.

Code Listing 11-12.

<HTML>
<HEAD>
<TITLE>Listing 11-12</TITLE>
<STYLE>
  .large {font-size: 24pt}
  .small {font-size: 8pt}
</STYLE>
</HEAD>
<BODY>
Standard text.
<H2 CLASS="small">The small class on an H2 element.</H2>
<SPAN CLASS="large">The large class on a SPAN element.</SPAN><BR>
<P CLASS="small">The small class on a P element.</P>
<B CLASS="large">The large class on a B element.</B><BR>
</BODY>
</HTML>

Click to view at full size.

Figure 11-12. All types of elements can be affected by a global class.


Links

Using dynamic styles, you can also change the style of the different states of a hypertext link, which is defined by the anchor tag, <A>. The anchor tag differs slightly from most other tags in that it has four states, called pseudoclasses. The four pseudoclasses are described here:

Pseudoclass | State | Default Appearance
link | The link has not been visited. | Blue with underline
visited | The link has been visited. | Purple with underline
hover | The mouse is resting over the link. | Blue with underline
active | The mouse is clicking the link. | Blue with underline

All of these pseudoclasses are available in Internet Explorer. Only link and visited work inside current versions of Netscape Navigator.

When you create a style sheet, you can modify the style of a pseudoclass by separating the pseudoclass name from the anchor tag with a colon, as shown here:

A:link {color: yellow}
A:visited {color: red}
A:hover {color: green}
A:active {color: blue}

Code Listing 11-13 demonstrates how these pseudoclasses can be used to create a simple text rollover effect in Internet Explorer.

Code Listing 11-13.

<HTML>
<HEAD>
<TITLE>Listing 11-13</TITLE>
<STYLE>
  A:link {text-decoration: none}
  A:hover {color: red; text-decoration: underline}
</STYLE>
</HEAD>
<BODY>
<A HREF="http://msdn.microsoft.com">msdn.microsoft.com</A><BR>
<A HREF="http://microsoft.com">microsoft.com</A><BR>
<A HREF="http://www.w3.org/style/">www.w3.org/style</A><BR>
<A HREF="http://www.w3.org">www.w3.org</A><BR>
</BODY>
</HTML>

Click to view at full size.

Figure 11-13. A link is highlighted and underlined when the mouse goes over it.

The first style (A:link) is used to set the normal appearance of links on the page. Setting text-decoration to none removes the underline from links on the page. When the user moves the mouse over a link, it enters the hover state and the style specified for A:hover takes effect, underlining the link and changing it to red.

NOTE
Generally, removing underlines from normal in-line hyperlinks is not recommended. Usability studies have shown that end users commonly interpret an underline below text as an indication that the text is a hyperlink. A lack of underlining can lead users to think that a link is not in fact a link. This effect is not as bad in the case of a menu of links—for example, in a left-hand menu navigation bar. Changing a link to boldface on mouseover is not recommended either because this changes the width of the text and might cause the page to reflow.


Cascading Styles

After all this discussion of Cascading Style Sheets (CSS), you might be wondering about the meaning of the term cascading. The CSS specification allows multiple style sheets to affect one document. Most of the time, the Web page creator specifies these style sheets. Users of some browsers (including Internet Explorer) can also create personal style sheets that affect the layout of the page—for example, by increasing the size or the color of text. When multiple style sheets interact, they are said to cascade with one another.

Obviously, conflicts can come up when various style sheets act on one document. In some browsers, the author's styles take precedence over the user's styles, while this is reversed in other browsers. Both author and user styles take precedence over default styles. When multiple author styles interact, the style referenced last generally takes precedence.

If you want to give additional weight to a particular style definition, you can append an important declaration to the definition as follows:

H2 {color: red!important; font-style: italic}

Notice the exclamation point that must be included between the style definition and the word important. Any definition without an important declaration is considered to be of normal weight. Style definitions with important declarations always take precedence over definitions of normal weight, regardless of who authored the definitions. Netscape Navigator does not currently support the important declaration.


Dynamic Styles

Throughout this chapter, we've used the term "dynamic styles." In Internet Explorer, styles truly are dynamic in that they can be changed at any time. This is accomplished through scripting. Code Listing 11-14 presents a simple example of changing a style with in-line script.

Code Listing 11-14.

<HTML>
<HEAD>
<TITLE>Listing 11-14</TITLE>
</HEAD>
<BODY>
<SPAN STYLE="color: red" onclick="this.style.color=`black'">
Click me!
</SPAN>
</BODY>
</HTML>

NOTE
When you are accessing styles through script, the naming convention differs slightly from that found in conventional CSS. Because most scripting languages do not allow a hyphen in an item name (they interpret the hyphen as a minus sign), CSS attribute names such as font-weight are not valid in script. Instead, by convention, the hyphen is omitted and the next letter is capitalized. Thus, the name font-weight is scripted as fontWeight. You can find more information about these naming conventions in Chapter 14.

This sample includes a SPAN element containing the text Click me! The text is normally red because of the in-line style set for the SPAN element. When the SPAN is clicked, a JScript event handler catches the click and changes the style by setting the color to black. Thus, when the red text is clicked, it turns black. Chapter 14 provides full details about similar techniques and scripting styles.

No currently available version of Netscape Navigator supports dynamic styles in this fashion. It is not supported in Internet Explorer 3 either. As a result, Code Listing 11-14 will not perform the color change in these browsers.

This chapter has provided an overview of dynamic styles. In the remaining chapters in Part 3, we will look at the specifics of font and text control through styles, how to specify the layout and position of elements on a page, and, finally, how to use script to make styles dynamic.


Chapter 12 -- Controlling Fonts and Text with Styles

 Chapter 12

Controlling Fonts and Text with Styles

Pure HTML has never allowed Web content developers to exercise a lot of control over text formatting. For example, tasks such as creating double-spaced text, modifying the space between letters in a word, and specifying custom fonts were almost impossible feats before style sheets came into use. The introduction of Cascading Style Sheets (CSS) made tasks like these relatively easy. In this chapter, we will take a look at the tools that CSS gives us for working with text, including font and text style attributes and font embedding.


Font-Based Attributes

The CSS attributes that specifically affect fonts (those that affect the appearance of individual characters of text) are font-family, font-style, font-variant, font-weight, and font-size. In addition, the font shorthand property enables you to change multiple font attributes simultaneously. The ways that Microsoft Internet Explorer 5 and Netscape Navigator display most of the attributes covered in this chapter are shown here in Figures 12-1 and 12-2.

Click to view at full size.

Figure 12-1. Some CSS formatting in Internet Explorer.

Click to view at full size.

Figure 12-2. The same page in Navigator 4.08.

Code Listing 12-1, a simple example of how you can use these attributes, begins with a global style sheet that establishes a series of style declarations for the SPAN element. Figure 12-3 shows how Internet Explorer displays this code. Notice the differences between the text that uses the style definition we created for SPAN and the text that does not.

Code Listing 12-1.

<HTML>
<HEAD>
<TITLE>Listing 12-1</TITLE>
<STYLE>
  SPAN {
    font-family: "Arial Western", Verdana, sans-serif;
    font-style:   italic;
    font-variant: small-caps;
    font-weight:  700;
    font-size:    18pt;
  }
</STYLE>
</HEAD>
<BODY>
This sentence is standard text that has no custom style.
This sentence is also standard text that has no custom style.
<HR>
<SPAN>This text uses the custom SPAN style we created.</SPAN>
<HR>
As you can see, some parts of this paragraph <SPAN>use our
custom SPAN style,</SPAN> and some do not. This paragraph
demonstrates how the two types of text can interact and how
line spacing or wrapping can be affected by mixing styles.
</BODY>
</HTML>

Click to view at full size.

Figure 12-3. An example of using CSS attributes to affect fonts.

The first attribute in this code's style sheet, font-family, specifies the typeface that Internet Explorer should use when displaying the font. This attribute is expressed as a prioritized list of fonts:

font-family: "Arial Western", Verdana, sans_serif

This line of code tells the browser to use the font named Arial Western, if possible. If this font is not available on the user's machine, the Verdana font should be used. If Verdana is not available, the code tells Internet Explorer to use a generic sans-serif font. Internet Explorer supports five generic font types: serif, sans-serif, cursive, fantasy, and monospace. Common examples of these font types are Times, Arial, Script, Ransom, and Courier, respectively. When a font name consists of more than a single word, the name should be enclosed in quotes. Netscape Navigator (at least through version 4) does not support the cursive generic font type.

NOTE
A serif font has small perpendicular lines at the ends of the main letter strokes. These lines, called serifs, can vary in length, thickness, and curvature. Many decorative fonts have long, curving serifs. The term "sans-serif" means "without serifs;" the letters of a sans-serif font are written in plain strokes, without the small perpendicular lines. For example, this letter T appears in a serif font. Notice the serifs at the bottom of the letter and on each end of the letter's top stroke. In contrast, this letter T is in a sans-serif font. A handy trick is to think of serifs as feet—if a font looks like it has feet, it is probably a serif font.

The second style declaration in Code Listing 12-1 includes the font-style attribute, which can be set to normal, italic, or oblique. A normal setting displays the text in roman (standard) type; an italic setting italicizes the text. Internet Explorer displays text with an oblique setting the same as italic. Netscape Navigator currently does not recognize the oblique setting.

The next attribute in the style sheet, font-variant, can be set to either small-caps (short for "small capital letters") or normal. With the small-caps setting, Internet Explorer renders text as all uppercase letters, but slightly smaller than normal capital letters of that font. Netscape Navigator does not recognize the font-variant attribute.

NOTE
Many CSS attributes are not supported by the current version of Netscape Navigator. However, Netscape has announced that the next full version of Navigator (Navigator 5) will be significantly more compliant with the CSS1 specification. You can find fairly good charts showing support by different browsers of all aspects of the CSS specifications at webreview.com/wr/pub/guides/style/style.html . The CSS1 Leader Board at webreview.com/wr/pub/guides/style/lboard.html shows what percentage of the CSS1 specification is supported by different browsers.

You can specify the weight, or thickness, of letters with the font-weight attribute, using the settings normal, bold, bolder, or lighter. The normal setting is the default. The bold setting makes the text somewhat bolder (darker) than its default. The bolder setting makes the text even bolder, whereas lighter makes the text somewhat less bold (lighter) than its default. As an alternative, you can use values in the range 100 to 900, in increments of 100, with 900 being the thickest and 400 the default. 700 is usually equivalent to a setting of bold.

The font-size attribute, which is also used in Code Listing 12-1, lets you control the size of the font. You can set this attribute in any of the following ways:

  • Using an exact size, such as 1pt. See the Units of Measurement section later in this chapter.

  • Using a percentage size relative to the default. For instance, a setting of 200% makes the font twice its normal size.

  • Using one of a set of keywords. Possible keywords are xx-small, x-small, small, medium, large, x-large, and xx-large. These values are relative to the user's font preference settings.

  • Using one of the two relative keywords larger and smaller. These values are relative to the size of the parent element.

    Finally notice the length of the style definition we set up in Code Listing 12-1:

    SPAN {
  font-family: "Arial Western", Verdana, sans-serif;
  font-style:   italic;
  font-variant: small-caps;
  font-weight:  700;
  font-size:    18pt;
}

If we had used the font shorthand property instead, we could have set up the same style definition with this code:

SPAN {
 font: small-caps italic 700 18pt "Arial Western", Verdana, sans-serif;
}

As you can see, using the font shorthand property can save a great deal of typing. As you learned in Chapter 11, however, shorthand properties are particular about the order in which their attributes are listed. When you use the font shorthand property, the settings of the three attributes font-style, font-variant, and font-weight must precede all other font attributes (although it is not important which of these three appears first). These attributes are optional. Next comes the font-size setting, which is required. Then you can include an optional line-height setting. (We will discuss this attribute in the following section.) Finally you must specify the font-family setting. For any of the optional attributes, you are free to simply omit the settings you don't need.


Text-Based Attributes

The attributes we have covered so far allow us to control the appearance of individual characters. Certain other CSS attributes allow you to change how groups of characters display. They include text-decoration, text-transform, text-align, text-indent, letter-spacing, and line-height. The color attribute is also commonly used with text. Code Listing 12-2 demonstrates how these attributes work; you can see the results in Figure 12-4.

Code Listing 12-2.

<HTML>
<HEAD>
<TITLE>Listing 12-2</TITLE>
<STYLE>
  DIV {
    text-align: justify;
    text-indent: 2em
  }
  SPAN {
    text-decoration: underline;
    text-transform: uppercase;
    vertical-align: super;
    letter-spacing: .5em;
    line-height: 200%;
    color: red
  }
</STYLE>
</HEAD>
<BODY>
These first two sentences are just standard text that has no
custom style. We have created style rules for SPAN and DIV
elements.
<HR>
Some more standard text.
<SPAN>This text uses the custom SPAN style we created.</SPAN>
<HR>
More standard text.
<DIV>
This whole paragraph is inside a DIV element. <SPAN>This
sentence is in a SPAN, which is in the DIV.</SPAN> This
paragraph demonstrates that DIV is a block element and SPAN
is an in-line element. Notice how the styles interact.
</DIV>
</BODY>
</HTML>

Click to view at full size.

Figure 12-4. An example of using CSS attributes to format text.

Code Listing 12-2 uses both SPAN and DIV elements. Both elements are very useful when working with styles, and the difference between the two is important. SPAN is an in-line element. This means that a SPAN element can be embedded in text without causing a line break; it flows with the paragraph just like the rest of the text in the paragraph. Some other common in-line elements are B (boldface), U (underline), and I (italic). In contrast, DIV is a block element. Block elements do not flow with the rest of the text in a paragraph. Instead, the DIV element is treated as a separate block of text and essentially becomes its own paragraph. Some other common block elements are P (paragraph), HR (horizontal rule), TABLE, and list elements such as UL, OL, and LI. Each of these causes a line break before it. Neither DIV nor SPAN elements visibly format characters, unlike most other elements, like B or LI. Code Listing 12-2 uses a DIV element because the text-align and text-indent attributes work only on block elements.

NOTE
Many CSS attributes apply only to block elements. Detailed descriptions of most attributes, including their effects on in-line and block elements, can be found on the SBN Workshop Web site and on the CD that accompanies this book. On the CD, go to Workshop (References); DHTML, HTML, & CSS; CSS; CSS Attributes Reference. To get to the online version, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm, or open the file named MSDN_OL.htm on the companion CD and choose CSS Attributes. To learn more about CSS, visit the site www.w3.org/Style/. The CSS1 specification itself can be found at www.w3.org/TR/REC-CSS1.

The text-align attribute controls the alignment of a block of text (such as a DIV element or a P element). You can set this attribute to left, right, center, or justify. The left setting left-justifies the text (aligns the lines of text evenly along the left edge of the text block), whereas the right setting right-justifies it. The center setting centers each line of text individually within the text block. Setting text-align to justify spaces out the text so that both the left and right indents are even (as you see in the normal text in this book).

The text-indent attribute determines how far the first line of the text block is indented. This attribute accepts standard units of measurement such as em and px as well as percentages. You can even assign a negative value, which results in a hanging indent. This attribute is especially handy when used with the P element, because it allows you to create a first-line indent for every new paragraph on a Web page.

Code Listing 12-2 also includes five other formatting attributes. The first, text-decoration, can be set to underline, overline, line-through, blink, or none. The underline, overline, and line-through settings cause lines to be drawn through the text at various heights (under, over, or through the text). Overline is not supported by Netscape Navigator 4. Though CSS provides for it, the blink setting is not rendered by Internet Explorer 4 or 5. You can set text-decoration to none to turn off any existing decorations in your text. For example, the following style definition for the anchor element (A) turns off the underline normally found beneath a hyperlink:

A {text-decoration: none}

The text-transform attribute controls the capitalization of text. The applicable values and their effects are as follows:

capitalize | Capitalizes the first letter of every word
uppercase | Capitalizes every letter of every word
lowercase | Lowercases all letters of all words
none | Resets any inherited capitalization; reverts to original setting.

The vertical-align attribute lets you set text to be either subscript or superscript. Its two possible settings are sub and super. This attribute does not allow you to set the exact distance the text is moved from the baseline. For this functionality, use relative positioning, described in the next chapter.

The letter-spacing attribute controls the distance between each letter in the text and is normally expressed in units of either px or em. The em unit is especially useful here because it changes the letter spacing relative to the size of the font in use.

Because setting the line-height attribute determines the overall size of the line of text, including the space above and below the characters, it has the effect of setting the line spacing. You can set this attribute by specifying a length (commonly in points or in ems, though any supported unit of measurement will work), a percentage, or a number of lines. (Numbers with decimal places are OK.) Thus, the following style definitions have the same effect:

DIV {font-size: 10pt; line-height: 20pt}
DIV {font-size: 10pt; line-height: 2em}
DIV {font-size: 10pt; line-height: 2}
DIV {font-size: 10pt; line-height: 200%}

The final attribute we used in Code Listing 12-2, color, sets the color of our text. You can set this attribute to one of the predefined colors in the color table, such as black or red. (The full color table appears on the SBN Workshop Web site and on the CD that accompanies this book. On the CD, go to Workshop (References); DHTML, HTML & CSS; DHTML References; Color Table. To get to the online version, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm, or open the file named MSDN_OL.htm on the companion CD and choose DHTML Color Table.) You can also use a setting expressed as either an RGB decimal triplet or an RGB hexadecimal triplet. RGB triplets let you specify values for the red, green, and blue components of the color, with each component set to a value in the range 0 through 255 decimal, or 00 through ff hexadecimal. Thus, the following three style definitions achieve identical results:

SPAN {color: blue}
SPAN {color: rgb(0,0,255)}
SPAN {color: #0000ff}


Units of Measurement

As seen in many of the examples above, you can use various standard units of measurement to set a length or a size in style sheets. How Internet Explorer displays different types of measurement units and a description of browser support for each unit is shown here:

Click to view at full size.


Font Embedding

The FONT element and the CSS font-family attribute allow you to specify a font to display, but they can specify only fonts the user already has. There is no guarantee that a person viewing the Web page has the desired font installed. Font embedding through the @font-face attribute lets you specify any font available to the designer and can practically guarantee that the user will have the font. This is accomplished by temporarily installing the specified font on the user's computer. The W3C formally included @font-face in the CSS level-2 specification.

Unfortunately, no version of Netscape Navigator currently supports the @font-face attribute. Netscape Navigator does, however, support a font embedding protocol from Bitstream known as TrueDoc. Bitstream has also released a downloadable Microsoft ActiveX control that adds TrueDoc support to Internet Explorer versions 4 and later. However, TrueDoc is not part of any W3C endorsed CSS specification and will not be covered in this text. Detailed information about TrueDoc can be found at www.truedoc.com.

How Font Embedding Works

Creating Web pages with embedded fonts is easy. The first step to creating the Web page is specifying fonts that you would like to use. (They must be available on your machine.) Code Listing 12-3 produces a simple Web page that specifies three fonts, without using embedded font technology. Figure 12-3 shows how Internet Explorer displays this code.

Code Listing 12-3.

<HTML>
<HEAD>
<TITLE>Listing 12-3</TITLE>
<STYLE>
  .crl {font-family: "Curlz MT"}
  .viv {font-family: "Vivaldi"}
  .stp {font-family: Stop}
  DIV  {font-size: 30pt}
</STYLE>
</HEAD>
<BODY>
<DIV CLASS="crl">This is some text using Curlz MT</DIV>
<DIV CLASS="viv">This is some text using Vivaldi</DIV>
<DIV CLASS="stp">This is some text using Stop</DIV>
</BODY>
</HTML>

Click to view at full size.

Figure 12-5. This Web page specifies three fonts that are not available on the target machine.

If the users viewing this Web page do not have the specified fonts on their computers (which is likely since they are uncommon), the page will not be displayed properly. The screen in Figure 12-5 is from a computer that did not have any of the specified fonts installed. Notice that all the text is in the standard browser font. This is not how we want the page to look.

To create downloadable font files and embed them within the page so that it looks the way we intend, we use a tool called WEFT, which stands for Web Embedding Font Tool. This tool is available on the companion CD in the \tools\msweft.exe file or from www.microsoft.com/typography . WEFT will analyze a Web page, determine what fonts it uses, create embedded versions of those fonts, and then, if desired, modify the original Web page so that it calls those fonts. Code Listing 12-4 shows what the code for the page looks like after WEFT completes its work. Figure 12-6 shows the resulting page. (The title of the page is still Listing 12-3 because the tool did not modify that line.)

NOTE
WEFT embeds the locations of files that are allowed to use a font, as well as the location of the font, in the embedded font itself. For security reasons, the font file will work only with files in the specified path. Because the use of the font file is limited, the risk of someone stealing the font for other uses is minimized. In Code Listing 12-4, the allowed path is D:\chap12\. If you try this example on the companion CD, your CD-ROM drive must be the D: drive. If you plan to use an EOT file on a Web server, you must point WEFT to a location on your Web server when it generates the fonts. This ensures that the path generated will point to your Web server and that the fonts will function there. You might need to copy the created fonts to your Web server. If you are generating them on your own machine for experimentation, use the file:// protocol; for example, file://D:\chap12\CURLZMT0.eot. These issues might become clearer if you look at the actual WEFT tool.

Code Listing 12-4.

<HTML>
<HEAD>
<TITLE>Listing 12-3</TITLE>
<STYLE>
  .crl {font-family: "Curlz MT"}
  .viv {font-family: "Vivaldi Italic"}
  .stp {font-family: Stop}
  DIV  {font-size: 30pt}
</STYLE>
<STYLE TYPE="text/css">
<!--
  @font-face {
    font-family: Curlz MT;
    font-style:  normal;
    font-weight: normal;
    src: url(file://D:\chap12\CURLZMT0.eot);
  }
  @font-face {
    font-family: Vivaldi;
    font-style:  normal;
    font-weight: normal;
    src: url(file://D:\chap12\VIVALDI0.eot);
  }
  @font-face {
    font-family: Stop;
    font-style:  normal;
    font-weight: normal;
    src: url(file://D:\chap12\STOP0.eot);
  }
-->
</STYLE>
</HEAD>
<BODY>
<DIV CLASS="crl">This is some text using Curlz MT</DIV>
<DIV CLASS="viv">This is some text using Vivaldi Italic</DIV>
<DIV CLASS="stp">This is some text using Stop</DIV>
</BODY>
</HTML>

Click to view at full size.

Figure 12-6. Embedded fonts display the text as intended.

The fonts that are created for download have an EOT file extension. So that the Web page finds the fonts properly, ensure that the EOT files created by WEFT are in the folder specified in the HTML file.

The modified page contains not only the font references we originally included in the file but also a series of @font-face style rules that tell the browser where to look for the font files. You can also add these @font-face rules by hand, though WEFT is necessary to create the embeddable fonts. Note that version 1 of WEFT sometimes has problems with fonts that have multiple word names.

Font Availability

Some font companies restrict the use of fonts to the purchaser. For this reason, you must not assume that any font that happens to be on your computer can be distributed with your Web page. TrueType fonts are encoded with embedding permissions that establish how conversion tools such as WEFT are allowed to use the fonts. The four levels of permission are shown in Table 12-1.

NOTE
Microsoft maintains a dedicated Web site containing information on Web typography issues. To see what Microsoft is doing in the area of Web-based typography, visit www.microsoft.com/typography. As of this writing, a beta version of WEFT version 2 was available from this Web site.

Table 12-1 Four Levels of Font Embedding Permission

Permission Level | Description
No embedding | The font creators do not allow their font to be embedded. (Often, however, the font creators might offer an alternate embeddable version.)
Print and preview | These fonts can be embedded only in pages that are static to the user. In other words, the page that uses the font cannot be "editable" by the user (as a page in a Web-based e-mail editor would be, for example).
Editable | These fonts can be embedded and do not carry the restrictions of the print and preview fonts.
Installable | These fonts are treated as editable by Internet Explorer, so they can be used as any normal font would be. Though they carry an Installable permission level, Internet Explorer does not install these fonts in the user's font folder. Because users could come across hundreds of these fonts throughout the Web, this restriction helps avoid cluttering users' computers with unwanted fonts.

In WEFT, you can easily determine the permission level of all the fonts on your computer by choosing Available Fonts from the View menu. WEFT will check all the fonts on your system and display a report like the one shown here, which tells you whether the font is okay to embed, is a Windows core font, is encoded as no embedding, is broken, or whether the font status is unknown:

Click to view at full size.


Chapter 13 -- Controlling Layout and Position with Styles

 Chapter 13

Controlling Layout and Position with Styles

In Chapter 12, you saw how CSS attributes and style sheets affect both fonts and text on Web pages. Styles can also be used to format and position elements, and control the overall layout of your Web pages. For example, using CSS, you can

  • Place a background image or a color behind an element

  • Create a custom border around a block of text

  • Set different margins around the top, bottom, left side, and right side of an image

  • Precisely tune the distance between an object and its borders

  • Place an object at an exact pixel location on the screen

NOTE
Many of the style attributes in this chapter are not properly displayed by Netscape Navigator 4. The good news is that by all indications Navigator 5 will comply much more closely with the CSS specifications and thus display styles properly.


Element Formatting

When planning the layout and formatting of an element, it is helpful to think of the element as surrounded by what are called formatting regions. Behind the element lies the background. The padding separates the element from its border. A margin lies around the border to separate this element from others. The padding, the border, and the margin each have top, bottom, left, and right components. Although not all of these formatting regions are relevant to every element, you will find many of them useful. The following illustration is a diagram of an element's formatting regions.

Click to view at full size.

Background-Based Attributes

Let's examine the five CSS attributes that affect the background of an element: background-color, background-image, background-repeat, background-position, and background-attachment. The background shorthand property lets you set all these attributes at one time.

Our first example, Code Listing 13-1, provides a simple demonstration of how the background-color attribute is used to specify the color that appears behind an element. Figure 13-1 shows how this code is displayed.

Code Listing 13-1.

<HTML>
<HEAD>
<TITLE>Listing 13-1</TITLE>
</HEAD>
<BODY>
<DIV>This has no style set.</DIV>
<DIV STYLE="background-color: red">
  This has background-color set.
</DIV>
</BODY>
</HTML>

Click to view at full size.

Figure 13-1. You can use the background-color attribute to change the color that appears behind an element.

The background-color attribute accepts any standard color unit as a setting, including a named color from the Color Table, an RGB decimal triplet, or an RGB hexadecimal triplet. (See Chapter 12.) To use a predefined color from the Color Table, consult the SBN Workshop Web site or the CD that accompanies this book. On the CD, see Workshop (References); DHTML, HTML & CSS; CSS; DHTML References; and then choose Color Table. To get to the online version, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm, or open the file named MSDN_OL.htm on the companion CD, and choose Color Table. To find out more about CSS attributes, on the CD go to Workshop (References); DHTML, HTML, & CSS; CSS; CSS Attributes Reference.

If you prefer to display an image instead of a flat color behind an element, you can use the background-image attribute. Code Listing 13-2 sets up an image as a background for the second DIV element. You can see the results in Figure 13-2.

Code Listing 13-2.

<HTML>
<HEAD>
<TITLE>Listing 13-2</TITLE>
</HEAD>
<BODY>
<DIV>This has no style set.</DIV>
<DIV STYLE="background-image: url(tile.gif)">
  This has background-image set.
</DIV>
</BODY>
</HTML>

Click to view at full size.

Figure 13-2. You can use the background-image attribute to display an image behind an element.

The background-image attribute has two possible settings: none and url (Uniform Resource Locator). Setting background-image to none removes any image that has been previously set. This attribute is typically used through script to change the background dynamically. When you set the background-image to url, you must also specify in parentheses the name and location of the file containing the image to be displayed, as shown in Code Listing 13-2.

When you specify the file location, you can give either an absolute path or a relative path to the target file. An absolute path provides the full location of the file—for example, http://www.microsoft.com/library/images/gifs/toolbar/home.gif. A relative path provides the location of the resource relative to the file that is calling for it. For instance, you can simply give the target filename if the two files are in the same directory. If the target resource file is in a subdirectory, you must give the subdirectory name followed by a slash and the filename. You can refer to a parent directory with two dots. Thus, if a directory contains two subdirectories named data and images, an HTML file in the data directory can set a background-image attribute to refer to a file named a.gif in the images directory with the code url(../images/a.gif). If referring to a file in a directory off the root of the same Web site as the calling page, simply use a forward slash before the directory name. For example, any page on the microsoft.com Web site could refer to a file at microsoft.com/images/a.gif as url(/images/a.gif).

When you use a background image behind an element, you can have the image repeated in any of several ways. Code Listing 13-3 offers some examples of how to use the background-repeat attribute. You can see the various visual effects in Figure 13-3 on the following page.

Code Listing 13-3.

<HTML>
<HEAD>
<TITLE>Listing 13-3</TITLE>
<STYLE>
  DIV {background-image: url(tile.gif); height: 44; width: 230}
</STYLE>
</HEAD>
<BODY>
<DIV>
  A global style sheet sets background-image for the DIV element.
</DIV>
<BR>
<DIV STYLE="background-repeat: repeat">
  This DIV has background-repeat set to repeat.
</DIV>
<BR>
<DIV STYLE="background-repeat: no-repeat">
  This DIV has background-repeat set to no-repeat.
</DIV>
<BR>
<DIV STYLE="background-repeat: repeat-x">
  This DIV has background-repeat set to repeat-x.
</DIV>
<BR>
<DIV STYLE="background-repeat: repeat-y">
  This DIV has background-repeat set to repeat-y.
</DIV>
</BODY>
</HTML>

Click to view at full size.

Figure 13-3. You can use the background-repeat attribute to repeat a background image in various ways.

NOTE
It is considered a good practice to include a background-color setting when using the background-image attribute (for example, STYLE="background-image: url(tile.gif); background-color: red"). Browsers that cannot display background images or cannot find the image file will use the specified background color instead. Later in this chapter, you will see how you can compress this code using the background shorthand property.

The default setting for the background-repeat attribute is repeat, which causes the image specified in the background-image attribute to repeat throughout the entire element. This setting is useful for creating continuous tiled backgrounds. To have a background image appear only once, you can set background-repeat to no-repeat. The repeat-x setting makes the image repeat only horizontally, whereas repeat-y makes it repeat only vertically.

You can use the background-position attribute to set the initial position of the background image relative to the element—that is, to specify where the background image should be placed horizontally and vertically behind the element. Code Listing 13-4 and Figure 13-4 show how the various settings of this attribute affect the position of the background image.

The background-position attribute accepts the keywords left, center, and right for setting the horizontal position and the keywords top, center, and bottom for setting the vertical position. It also allows measurements expressed in standard units such as px (pixels) and percentages. (See the Units of Measurement table in Chapter 12 for a list of standard measurement units.) This attribute is especially useful when you are working with the BODY element. For example, you can make an image appear to be centered behind the entire page, both horizontally and vertically, by setting the background-position attribute for the BODY element to center center.

Code Listing 13-4.

<HTML>
<HEAD>
<TITLE>Listing 13-4</TITLE>
<STYLE>
  DIV {background-image: url(tile2.jpg); height: 75; width: 275;
       border: solid 1px black; float: left; margin: 5px}
</STYLE>
</HEAD>
<BODY>
<DIV>
  A global style sheet sets background-image, width, and height
  for the DIV element. This uses the default background-position.
</DIV>

<DIV STYLE="background-position: bottom right">
  This DIV has background-position set to bottom
  right
</DIV>

<DIV STYLE="background-position: 25% 10px; background-repeat: no-repeat">
  This DIV has background-position set to 25% 10px and
  background-repeat set to no-repeat.
</DIV>

<DIV STYLE="background-position: center center">
  This DIV has background-position set to center center.
</DIV>
</BODY>
</HTML>

Click to view at full size.

Figure 13-4. You can use the background-position attribute to control where the background image is placed.

The background-attachment attribute, which can be used only on the BODY element, specifies whether the background image scrolls with the rest of the page. The scroll setting is the default. To create the effect of the elements on the page sliding over the background when the user scrolls, set the background-attachment attribute to fixed. Netscape Navigator 4 does not support this attribute.

To set all of these background-based attributes simultaneously, you can use the background shorthand property. The individual attributes must be set in this order: background-color, background-image, background-repeat, background-attachment, and background-position. All of these attributes are optional; simply omit any that you do not want to set. Let's look at an example of a style definition using the background attributes:

DIV {
    background-color: red;
    background-image: url(tile.gif);
    background-repeat: no-repeat;
    background-position: center center;
    }

This style definition could be compressed to the following line of code:

DIV {background: red url(tile.gif) no-repeat center center}

Border-Based Attributes

CSS allows you to exercise precise control over the border of an element (a visible line around part or all of an element). You can set the width, style, and color of all sides of a border at one time, or you can specify the characteristics of each side of the border individually.

The border-width attribute defines the width of the border around an element. This attribute accepts the keywords thin, medium, and thick as well as measurements expressed in standard units, such as px, em, and pc. Note that in Netscape Navigator 4, the medium and thick settings are thicker than the same settings in Microsoft Internet Explorer. In Code Listing 13-5, we used different width settings for several borders; Figure 13-5 shows the variation.

Code Listing 13-5.

<HTML>
<HEAD>
<TITLE>Listing 13-5</TITLE>
<STYLE>
  DIV {border: groove red}
</STYLE>
</HEAD>
<BODY>
<DIV STYLE="border-width: thin">border-width of thin.</DIV>
<BR>
<DIV STYLE="border-width: medium">border-width of medium.</DIV>
<BR>
<DIV STYLE="border-width: thick">border-width of thick.</DIV>
<BR>
<DIV STYLE="border-width: 10px">border-width of 10px.</DIV>
<BR>
<DIV STYLE="border-width: 1em">border-width of 1em.</DIV>
</BODY>
</HTML>

Click to view at full size.

Figure 13-5. With the border-width attribute, you can vary the widths of borders.

The border-style attribute lets you define the style of the border around the element. You can specify any of these styles: none, solid, double, groove, ridge, inset, and outset. (The inset and outset border styles often do not work well on 256-color displays, in which intermediate colors appear poorly blended.) Code Listing 13-6 provides an example of some of these effects, as illustrated in Figure 13-6.

Code Listing 13-6.

<HTML>
<HEAD>
<TITLE>Listing 13-6</TITLE>
<STYLE>
  DIV {border: 9px red}
</STYLE>
</HEAD>
<BODY>
<DIV STYLE="border-style: none">border-style of none.</DIV>
<BR>
<DIV STYLE="border-style: solid">border-style of solid.</DIV>
<BR>
<DIV STYLE="border-style: double">border-style of double.</DIV>
<BR>
<DIV STYLE="border-style: groove">border-style of groove.</DIV>
<BR>
<DIV STYLE="border-style: inset">border-style of inset.</DIV>
<BR>
<DIV STYLE="border-style: outset">border-style of outset.</DIV>
<BR>
</BODY>
</HTML>

Click to view at full size.

Figure 13-6. You can change the style of a border with the border-style attribute.

The border-color attribute sets the color of all four sides of the border simultaneously. It accepts the same standard color settings as the background-color attribute (discussed in the preceding section). Some border styles, such as groove, inset, and outset, are composed of multiple colors to create a three-dimensional effect. These border styles use the border-color setting as the base color but might shade or lighten it to enhance the 3-D effect.

Rather than setting the border-width, border-style, and border-color attributes separately, you can use the border shorthand property to simultaneously specify the width, style, and color of an entire border, as shown in Code Listing 13-7. The resulting border appears in Figure 13-7.

Code Listing 13-7.

<HTML>
<HEAD>
<TITLE>Listing 13-7</TITLE>
<STYLE>
  DIV {border: 10px double red}
</STYLE>
</HEAD>
<BODY>
<DIV>This has the same border on all sides.</DIV><BR>
</BODY>
</HTML>

Click to view at full size.

Figure 13-7. You can use the border shorthand property to set the width, style, and color of an entire border at one time.

All of the attributes included in the border shorthand property are optional and can be listed in any order. If you omit one of the attribute settings, Internet Explorer will display the default for that attribute. For example, if you omit the color setting, the resulting border will be black, the default. One important note: if you omit a border-style setting, Internet Explorer uses the default setting none—which means that there will be no visible border.

The border-left, border-right, border-top, and border-bottom attributes let you set the width, style, and color for one side of a border at a time. These attributes are not supported in Netscape Navigator 4. For instance, Code Listing 13-8 demonstrates how to set up a different border on each side of an element. Figure 13-8 shows the resulting page.

Code Listing 13-8.

<HTML>
<HEAD>
<TITLE>Listing 13-8</TITLE>
<STYLE>
  DIV {
    border-top: 10px double black;
    border-bottom: none;
    border-left: 20px solid red;
    border-right: 15px groove green;
  }
</STYLE>
</HEAD>
<BODY>
<DIV>This has a different border on each side.</DIV>
</BODY>
</HTML>

Click to view at full size.

Figure 13-8. Each side of this element has a different border.

You can also use even more specific CSS attributes to fine-tune particular aspects of a border. These attributes, which are not supported in Netscape Navigator 4 (though they are supported in Internet Explorer, Opera (a small, fast browser that requires only 1 MB of disk space), and most likely Navigator 5), include the following:

border-left-width | border-right-width | border-top-width | border-bottom-width
border-left-style | border-right-style | border-top-style | border-bottom-style
border-left-color | border-right-color | border-top-color | border-bottom-color

These attributes can be mixed and matched to produce the desired effect. For example, the following style definition creates a 10-pixel-wide, red double border, except on the left side, which has no border, and on the bottom, where the border is only 5 pixels thick.

DIV {border: 10px double red; border-left-style: none;
      border-bottom-width: 5px}

Padding-Based and Margin-Based Attributes

The amount of space around an element is controlled with the padding and margin attributes. The padding attribute sets the spacing between an element and its border; the margin attribute sets the spacing between the border and any other elements. Additional and more specific attributes such as padding-right and margin-top allow you to set a different size padding and margin for each side of a border.

Code Listing 13-9 demonstrates several of the major layout attributes, including padding and margin. The DIV elements have a light gray background that extends through a 20-pixel padding to a 10-pixel-wide, solid blue border. They are separated from their surroundings by 30-pixel margins. Figure 13-9 on the following page shows an example of the padding and margin attributes. Netscape Navigator 4.08 displays the same code with a slight gap between the padding and the margin (where the body color will show through). This indicates that although Navigator 4 supports both padding and margin, its behavior does not completely conform to the CSS specifications. This problem will likely be corrected in Navigator 5.

Code Listing 13-9.

<HTML>
<HEAD>
<TITLE>Listing 13-9</TITLE>
<STYLE>
  DIV {
    padding: 20px;
    margin: 30px;
    background: darkgray;
    border: 10px solid black;
    height: 50px;
    width: 300px
  }
</STYLE>
</HEAD>
<BODY>
<DIV>
  A global style sheet sets many attributes for the DIV element.
</DIV>
<DIV>
  A global style sheet sets many attributes for the DIV element.
</DIV>
</BODY>
</HTML>

Click to view at full size.

Figure 13-9. The padding and margin attributes control the spacing around an element.


Page Layout

In addition to the attributes discussed so far, CSS also provides attributes that let you control whether an element is displayed, the location of an element on the screen, and the relative position of each element.

Two-Dimensional Positioning Attributes

CSS Positioning, also known as CSS-P, is part of the official Cascading Style Sheets level 2 specification. The primary tools for positioning an element are the position, top, and left attributes, which are demonstrated in Code Listing 13-10. Figure 13-10 shows the results.

The top and left attributes are set using standard CSS units of measurement. These settings specify how far away the top or left edge of an element (defined as the edge of the element's margin) will be located from a base point. The base point is determined by the position attribute setting. To use either the top or left attribute, you must first set the position attribute.

Code Listing 13-10.

<H\TML>
<HEAD>
<TITLE>Listing 13-10</TITLE>
<STYLE>
.span1 {position: absolute; top: 0px; left: 0px;
        background: blue}
.span2 {position: absolute; top: 25%; left: 25%;
        width: 50%;
        background: lightgrey}
.span3 {position: relative; top: 3px;
        background: red}
.span4 {position: absolute; top: 75px; left: 25px;
        width: 50%;
        background: green}
</STYLE>
</HEAD>
<BODY>

<SPAN CLASS="span1">SPAN #1 has position set to absolute.</SPAN>

<SPAN CLASS="span2">
  SPAN #2 has position set to absolute.
  The following word <SPAN CLASS="span3">relative</SPAN>
  is in SPAN #3, which has position set to relative.

  <SPAN CLASS="span4">
    SPAN #4 is contained by SPAN #2 and has position
    set to absolute.
  </SPAN>

  This is the last text in SPAN #2.
</SPAN>

</BODY>
</HTML>

Click to view at full size.

Figure 13-10. Using the position, top, and left attributes to position elements on a page.

The position attribute has three possible settings: static, absolute, and relative. The default is static, which means that the browser should position the element in its normal place and ignore settings for the top and left attributes.

Setting the position attribute to absolute allows you to place an element an exact distance from the top left corner of its parent element (the element that contains it). For example, the parent element for SPAN #1 in Code Listing 13-10 is the BODY element, or in other words, the entire page. Setting position to absolute and both top and left to 0 places the SPAN element at the upper left of our page. Because the parent element of SPAN #4 is SPAN #2, its values for the top and left attributes are based on the top left corner of SPAN #2 rather than on the BODY element.

The relative setting allows you to position an element a specified distance from its normal location. Using relative positioning, SPAN #3 is placed 3 pixels lower than its normal location.

NOTE
Code Listing 13-10 is rendered somewhat differently by different vendors' browsers. Whenever you're using positioning, it is especially important to test it in all your target browsers.

It is often thought that the difference between absolute and relative settings is that absolute sets the distance in pixels and relative sets the distance in percentages. This is incorrect. Both absolute and relative allow both pixels and percentages as units of measurement.

Positioning in the Third Dimension

It is possible to use positioning to place two elements on a page at the same location. Normally, the item that is listed last in the HTML code appears on top. You can control this by using the z-index attribute to position elements in front of or behind one another. Code Listing 13-11 provides an example of setting the z-index attribute. In Figure 13-11, you can see the different effects it created.

In Code Listing 13-11, we used two images and one SPAN element containing text. The z-index attribute of the SPAN element was set to 0, while the z-index attributes of the images were set to -1 and 1. The image whose z-index setting is 1 appears in front of the SPAN text (z-index of 0), whereas the image whose z-index setting is -1 appears behind the text. Like top and left, the z-index attribute works only on elements whose position attribute has been set to either absolute or relative. Though Navigator 4 has problems with this code, Navigator 5 will most likely support z-index.

Code Listing 13-11.

<HTML>
<HEAD>
<TITLE>Listing 13-11</TITLE>
<STYLE>
  .img1  {position: absolute; top: 100px; left: 150px; z-index: 1}
  .span1 {position: absolute; top: 90px; left: 60px; z-index: 0}
  .img2  {position: absolute; top: 100px; left: 330px; z-index: -1}
</STYLE>
</HEAD>
<BODY>
<IMG CLASS="img1" SRC="one.gif" >
<SPAN CLASS="span1">
  This SPAN has a z-index value between those of the two images.
</SPAN>
<IMG CLASS="img2" SRC="two.gif">
</BODY>
</HTML>

Click to view at full size.

Figure 13-11. You can use the z-index attribute to place elements in front of or behind other elements.

Display and Visibility

So far, you have learned to control how and where an element is placed on the page. The display and visibility attributes let you control whether an element appears on the page at all. Code Listing 13-12 uses both these attributes. Figure 13-12 shows the resulting display in the Internet Explorer window.

Code Listing 13-12.

<HTML>
<HEAD>
<TITLE>Listing 13-12</TITLE>
</HEAD>
<BODY>
<IMG SRC="one.gif" STYLE="visibility: visible">
<IMG SRC="two.gif" STYLE="visibility: hidden">
<IMG SRC="three.gif">
<IMG SRC="four.gif" STYLE="display: none">
<IMG SRC="five.gif" STYLE="display: inline">
<IMG SRC="six.gif" STYLE="display: block">
<IMG SRC="seven.gif" STYLE="display: list-item">
</BODY>
</HTML>

Click to view at full size.

Figure 13-12. The display and visibility attributes let you control whether an element is displayed on your page.

Both the display and visibility attributes allow you to prevent an element from being shown. Setting the visibility attribute to hidden makes the element invisible, although it still takes up space on the screen. The default setting for the visibility attribute is visible, which means that the element is displayed and takes up space on the screen as usual.

Setting the display attribute to none not only causes the element to disappear from view but also frees up space on the screen, thereby allowing other elements to collapse into this unoccupied space. Notice, for example, how in Figure 13-12, because image four's display attribute is set to none, the space it would normally occupy is filled by image five. Setting this attribute to any value other than none—setting it to block, inline, or list-item—causes the element to be displayed. In Internet Explorer 4, block, inline, and list-item are treated identically. In Internet Explorer 5, they cause the element to display as a block element (with a line break in front of it), an inline element (flowing normally like one word in a sentence), or as standard text. Future versions of Internet Explorer might give better support for list items.

Controlling Partial Display

You've already seen how the height and width attributes can control the size of elements on the screen. The overflow CSS attribute lets you decide what happens to parts of an element that do not fit within the prescribed height and width. Code Listing 13-13 demonstrates the overflow attribute. Figure 13-13 shows how Internet Explorer displays this code. Netscape Navigator 4 does not support the overflow attribute.

Code Listing 13-13.

<HTML>
<HEAD>
<TITLE>Listing 13-13</TITLE>
<STYLE>
  DIV {
    background: darkgray;
    width: 75;
    height: 75;
    margin: 10;
    float: left;
    }
</STYLE>
</HEAD>
<BODY>
A global style sheet sets the background color, height, width,
margin, and float for all DIVs. The float allows the DIVs to
display on the same line. Notice how wide lines (a series of
W's) are handled in each case.
<DIV>
  WWWWWWWW A standard DIV, with no additional styles specified.
  It expands beyond the height specified to hold all the text.
</DIV>
<DIV STYLE="overflow:visible">
  WWWWWWWW This DIV specifies an overflow of visible.
  It also expands beyond the height specified.
</DIV>
<DIV STYLE="overflow:hidden">
  WWWWWWWW This DIV specifies an overflow of hidden.
  This one is completely restricted to the specified size.
</DIV>
<DIV STYLE="overflow:scroll">
  WWWWWWWW This DIV specifies an overflow of scroll.
  Both scroll and both vertical and horizontal scrollbars appear.
</DIV>
<DIV STYLE="overflow:auto">
  WWWWWWWW This DIV specifies an overflow of auto.
  This means that scrollbars appear where needed.
</DIV>
<DIV STYLE="overflow:auto">
  This DIV specifies an overflow of auto.
  Without the W's, only a vertical scroll bar appears.
</DIV>
</BODY>
</HTML>

Click to view at full size.

Figure 13-13. The overflow attribute controls how a constrained-size element is displayed on your page.

Figure 13-13 displays six different DIVs. A global stylesheet has specified a height and width of 75 pixels for all DIV elements. It also specifies other attributes, including float, which will be covered later in this chapter. Note how the first DIV, which has no overflow attribute set, expands to fit the text. The rest of the DIVs on the page use the overflow attribute, which has four possible values, visible, hidden, scroll, and auto. The second DIV has overflow set to visible. This is the default value for overflow, and the element behaves identically to the first DIV. The third DIV sets overflow to hidden. This causes the element to cut off any part that does not fit into the prescribed width and height. Setting overflow to scroll makes both horizontal and vertical scroll bars appear. This is true whether or not scroll bars are required for content. Finally, the auto value causes scroll bars to appear only where necessary. Notice how the fifth DIV contains both a horizontal scroll bar (which allows you to scroll across the series of W's) and a vertical scroll bar (which allows you to scroll down through the text). Because the W's are removed from the final DIV, it has only a vertical scroll bar. The clip attribute allows you to control which parts of an element are displayed. For example, with clip you can make just the center, top right, or bottom half of an object visible. Code Listing 13-14 demonstrates the clip attribute, while Figure 13-14 displays its results.

Code Listing 13-14.

<HTML>
<HEAD>
<TITLE>Listing 13-14</TITLE>
<STYLE>
IMG {position:absolute}
</STYLE>
</HEAD>
<BODY>
<IMG SRC="three.gif" STYLE="left: 0">
<IMG SRC="three.gif" STYLE="left: 40; clip: auto">
<IMG SRC="three.gif" STYLE="left: 80; clip: rect(0 20 20 0)">
<IMG SRC="three.gif" STYLE="left: 120; clip: rect(5 30 30 5)">
<IMG SRC="three.gif" STYLE="left: 160; clip: rect(5 20 auto 0)">
</BODY>
</HTML>

Click to view at full size.

Figure 13-14. The clip attribute lets you crop an object to a particular size.

Using the clip attribute is like cropping an image in desktop publishing. Clip specifies a rectangular piece of the element to display. Clip has two potential values, auto and rect (top right bottom left). The auto setting is the default and causes the entire element to display. The rect setting lets you specify four values that define a rectangle through which you view the element. The four settings specify how far from the top and left edges of the element the top, right, bottom, and left edges of the viewing window should be. For example, the first setting is how far the topmost part of the viewing rectangle should be located from the top of the element. Notice that the third IMG element in Figure 13-14 has the top component of the rect value set to 0, and the entire top of the image is displayed; whereas the fourth IMG, which is set to 5, has 5 pixels cut off the top. In the fourth IMG, the viewing window begins 5 pixels from the top and left of the element and extends to 30 pixels from the left and the top of the element. Any of the four rect settings can be set to auto. This setting allows that edge of the viewing window to extend to the edge of the element. To use this attribute, the elements must be positioned with the absolute setting. Note that clip is not supported by Navigator 4 or Opera 3.5.

The float and clear Attributes

In Code Listing 13-13 we used the float attribute to cause DIV elements to line up next to one another, rather than on top of one another. The float attribute is used to take elements out of their normal place in the document and let other elements wrap around them. The clear attribute lets you specify where floating elements are not allowed. Code Listing 13-15 demonstrates both the float and clear attributes. Figure 13-15 shows how Internet Explorer displays this code.

Code Listing 13-15.

<HTML>
<HEAD>
<TITLE>Listing 13-15</TITLE>
<STYLE>
DIV {width: 100; background: darkgray}
</STYLE>
</HEAD>
<BODY>
<DIV STYLE="float: left">This DIV uses float left.</DIV>
<SPAN>
The DIV element has a value set for float.
Note how it floats on the side specified.
</SPAN>
<P>
<DIV STYLE="float: left">This DIV uses float left.</DIV>
<SPAN STYLE="clear: left">
In this SPAN, the clear CSS attribute has been set to left.
This means that it will not allow floating elements to its left.
</SPAN>
</BODY>
</HTML>

Figure 13-15. The float and clear attributes let you control the flow of text around objects.

Figure 13-15 displays two different SPANs. Before each SPAN is a DIV with a value set for float. Float may be set to left, right, or none. None causes it to behave as though it had no float. Because the DIV is set to float left, it appears to the left of the SPAN.

NOTE
Although float is supported by many different HTML elements, when it is used on a SPAN or DIV, the element must have a width specified.

The clear attribute is demonstrated in the second SPAN in Figure 13-15, which has clear set to left. This means that elements are not allowed to float on its left side. The clear attribute allows settings of none, left, right, and both. The default setting of none allows elements to float freely. A setting of both restricts elements from floating on either the left or the right.

The CSS attributes that we have used so far have dealt primarily with text and other standard Web components. In the next chapter, we will look at using CSS to control other browser features such as the cursor, tables, lists, and printing.


Chapter 14 -- Controlling Other Browser Elements with CSS

 Chapter 14

Controlling Other Browser Elements with CSS

In addition to the CSS attributes we have covered thus far, there are a number of others that control nontextual elements, such as the cursor, printing behavior, tables, and lists. Many of the attributes in this chapter are new, proposed, or considered less important aspects of older specifications. As such, they have less widespread support than many other CSS attributes.


Controlling Tables with CSS

In the CSS level-2 specification are two new table-specific attributes, border-collapse and table-layout. Though supported by Microsoft Internet Explorer 5, these attributes are not supported by Internet Explorer 4 or Netscape Navigator.

The border-collapse Attribute

The border-collapse CSS attribute allows finer table borders than ever. This attribute accepts only two values, collapse and separate. A value of separate is the default and causes the table to display as normal. Code Listing 14-1 demonstrates this attribute, and Figure 14-1 displays the results.

Code Listing 14-1.

<HTML>
<HEAD>
<TITLE>Listing 14-1</TITLE>
</HEAD>
<BODY>

This is a standard table, with BORDER="1".
<TABLE BORDER="1">
  <TR>
    <TD>Information</TD><TD>Information</TD><TD>Information</TD>
  </TR>
  <TR>
    <TD>Information</TD><TD>Information</TD><TD>Information</TD>
  </TR>
</TABLE>
<P>

This is a standard table, with BORDER="1" and CELLSPACING="0".
<TABLE BORDER="1" CELLSPACING="0">
  <TR>
    <TD>Information</TD><TD>Information</TD><TD>Information</TD>
  </TR>
  <TR>
    <TD>Information</TD><TD>Information</TD><TD>Information</TD>
  </TR>
</TABLE>
<P>

This table also has BORDER="1", and has the CSS attribute
border-collapse set to collapse.
<TABLE STYLE="border-collapse:collapse" BORDER="1">
  <TR>
    <TD>Information</TD><TD>Information</TD><TD>Information</TD>
  </TR>
  <TR>
    <TD>Information</TD><TD>Information</TD><TD>Information</TD>
  </TR>
</TABLE>
</BODY>
</HTML>

Click to view at full size.

Figure 14-1. Using border-collapse to collapse a table's border.

The first table in Figure 14-1 is a conventional table with BORDER="1". Every cell has a border, and there is a border around the entire table. Cells are separated from each other and the outside border by the default of 2 pixels. The second table has the CELLSPACING attribute set to 0, so no space is allowed between neighboring cell borders. However, this creates the appearance of a 2-pixel thick border around each cell, since each cell has its own 1-pixel thick border. In the third table, the border-collapse attribute is set to collapse. With this attribute, both the space between borders and the borders themselves are shrunk, separating each cell from its neighbors by only a 1-pixel thick border. These collapsed borders approximate those found in many other types of programs, such as Microsoft Excel and Microsoft Access.

The table-layout Attribute

The table-layout CSS attribute was designed to address some performance concerns with displaying tables in a browser. A feature of conventional tables is that they conform to their contents. For example, if a particular cell contains a wide entry, the width of the entire column expands to the width of the widest entry. One drawback to this feature is that before the table can be displayed, the entire table must first be read in so that the widest cell can be determined. When table-layout is fixed, you can enter an arbitrary width for all the cells in the table, regardless of their contents. This feature can greatly increase rendering performance, especially when working with large tables. Code Listing 14-2 demonstrates the use of this attribute in combination with the height and width attributes.

Code Listing 14-2.

<HTML>
<HEAD>
<TITLE>Listing 14-2</TITLE>
</HEAD>
<BODY>
This is a standard table.
<TABLE BORDER="1">
  <COL WIDTH="50"><COL WIDTH="50"><COL WIDTH="200">
  <TR HEIGHT="20">
    <TD>Information</TD><TD>Information</TD><TD>Information</TD>
  </TR>
  <TR HEIGHT="20">
    <TD>Wider Column</TD><TD>Information</TD><TD>Information</TD>
  </TR>
</TABLE>
<P>
This is the same table, but with table-layout set to fixed.
<TABLE BORDER="1" STYLE="table-layout:fixed">
  <COL WIDTH="50"><COL WIDTH="50"><COL WIDTH="200">
  <TR HEIGHT="20">
    <TD>Information</TD><TD>Information</TD><TD>Information</TD>
  </TR>
  <TR HEIGHT="20">
    <TD>Wider Column</TD><TD>Information</TD><TD>Information</TD>
  </TR>
</TABLE>
<P>
This is the same table, with table-layout set to fixed and row
height removed.
<TABLE BORDER="1" STYLE="table-layout:fixed">
  <COL WIDTH="50"><COL WIDTH="50"><COL WIDTH="200">
  <TR>
    <TD>Information</TD><TD>Information</TD><TD>Information</TD>
  </TR>
  <TR>
    <TD>Wider Column</TD><TD>Information</TD><TD>Information</TD>
  </TR>
</TABLE>
</BODY>
</HTML>

Click to view at full size.

Figure 14-2. Using a table-layout of fixed to control the layout of a table.

Figure 14-2 displays three tables. Each of the tables contains the same data. The first is a conventional table that uses COL elements to set the width of the first two columns at 50 pixels and the third at 200 pixels. Because 50 pixels is not wide enough to hold the entire word "Information," the cells expand to fit the text. Each row in the table has a specified height tall enough to hold one line of text. However, because the second row contains a cell with two lines of text, all three cells in the second row expand vertically.

The second table has its table-layout attribute set to fixed. A fixed value causes the table to accept the width and height specified in the COL and TR elements, regardless of the cells' contents. Any lines too wide for a cell are either wrapped or truncated, and any content too tall for a cell is truncated.

The third table is exactly like the second, except that the rows do not have a height specified. This means that the contents of a cell can expand vertically but not horizontally.

This particular table is not sufficiently large to notice any improvements in performance, but it does demonstrate the absolute nature of the cell dimensions. LrgTable.htm in the chap14 folder on the companion CD demonstrates the significant speed differences between two tables, one of which uses a table-layout of fixed, and one that does not specify any table-layout.


Controlling the Cursor with CSS

The cursor CSS attribute allows you to change the display of the mouse pointer, for example, from a pointing finger to a hand icon or to an arrow. This can be helpful in a variety of circumstances. If, for instance, you want to signify to the user that an image is clickable, you can set the image's cursor style to hand. Code Listing 14-3 demonstrates all the different settings for the cursor attribute. Figure 14-3 displays what the cursor looks like when it is positioned over each of the cells.

Code Listing 14-3.

<HTML>
<HEAD>
<TITLE>Listing 14-3</TITLE>
</HEAD>
<BODY>
<TABLE BORDER="1" CELLSPACING="0" CELLPADDING="4">
  <TR HEIGHT="50" VALIGN="TOP">
    <TD STYLE="cursor:auto">auto</TD>
    <TD STYLE="cursor:hand">hand</TD>
    <TD STYLE="cursor:move">move</TD>
    <TD STYLE="cursor:text">text</TD>
    <TD STYLE="cursor:wait">wait</TD>
    <TD STYLE="cursor:help">help</TD>
    <TD STYLE="cursor:default">default</TD>
    <TD STYLE="cursor:crosshair">crosshair</TD>
  </TR>
</TABLE>
<BR>

<TABLE BORDER="1" CELLSPACING="0" CELLPADDING="4">
  <TR HEIGHT="50" VALIGN="TOP">
    <TD STYLE="cursor:w-resize">w-resize</TD>
    <TD STYLE="cursor:nw-resize">nw-resize</TD>
    <TD STYLE="cursor:n-resize">n-resize</TD>
    <TD STYLE="cursor:ne-resize">ne-resize</TD>
    <TD STYLE="cursor:e-resize">e-resize</TD>
    <TD STYLE="cursor:se-resize">se-resize</TD>
    <TD STYLE="cursor:s-resize">s-resize</TD>
    <TD STYLE="cursor:sw-resize">sw-resize</TD>
  </TR>
</TABLE>
</BODY>
</HTML>

Click to view at full size.

Figure 14-3. The cursor CSS attribute controls the display of the mouse pointer.

The sixteen potential values for the cursor attribute are auto, hand, move, text, wait, help, default, crosshair, w-resize, nw-resize, n-resize, ne-resize, e-resize, se-resize, s-resize, and sw-resize. They display as shown in Figure 14-3. Netscape Navigator 4 does not support this attribute.


Controlling Printing with CSS

The page-break-before and page-break-after CSS attributes do not modify the display of the page on the screen. Instead, they are used to control how the document prints. Each of these attributes accepts four values; auto, always, left, and right. Auto is the default, and page breaks are inserted only as needed. Setting page-break-before to always causes the printer to begin a new page whenever it reaches the specified element. A page-break-before of left causes page breaks to be inserted until the specified element appears on a blank left page. A page-break-before of right causes page breaks to be inserted until the element appears on a blank right page. The page-break-after attribute controls page breaks after the element, instead of before. Code Listing 14-4 on the following page demonstrates these attributes, and Figure 14-4 shows the display of the page on the screen.

Code Listing 14-4.

<HTML>
<HEAD>
<TITLE>Listing 14-4</TITLE>
</HEAD>
<BODY>
<DIV>This is the first DIV.</DIV>
<DIV STYLE="page-break-before:always">This is the second DIV.</DIV>
<DIV STYLE="page-break-after:always">This is the third DIV.</DIV>
<DIV>This is the fourth DIV.</DIV>
<DIV STYLE="page-break-before:right">This is the fifth DIV.</DIV>
<DIV STYLE="page-break-after:right">This is the sixth DIV.</DIV>
<DIV>This is the last DIV.</DIV>
</BODY>
</HTML>

Click to view at full size.

Figure 14-4. The CSS attributes page-break-before and page-break-after affect the appearance of the printout, not the displayed page.

This listing results in a five-page printout. The first page contains only the first DIV. The second DIV has its page-break-before CSS attribute set to always, so a page break is inserted before the DIV and it appears on the second page. The third DIV also appears on the second page. It has page-break-after set to always, so the page breaks after this element. Setting values of left and right causes page breaks in Internet Explorer 4. Internet Explorer 5 should insert one or two page breaks until either a left or right page, as appropriate.

NOTE
Some late betas of Internet Explorer 5 do not support the values left and right. Netscape Navigator 4 does not support the page-break attributes.


Controlling Lists with CSS

There are several CSS attributes that can affect the appearance of HTML lists. The list-style-type attribute allows you to choose from nine types of item markers, and list-style-image lets you use graphics as item markers. The list-style-position attribute controls the wrapping of an item's text relative to its marker, and list-style is a shortcut property that controls all the list-style attributes. Code Listing 14-5 demonstrates the list-style-type attribute, and Figure 14-5 on the following page displays the results.

The list-style-type CSS attribute is similar to, but more flexible than, the HTML attribute named TYPE. Nine values are available for list-style-type: disc, circle, square, none, decimal, lower-roman, upper-roman, lower-alpha, and upper-alpha. The first four values allow you to set a shape in front of the items in the list. The remaining values specify ordering schemes. A value of decimal causes the items to be ordered using the base-10 numbering system. A value of lower-roman causes the items to be ordered using lowercase roman letters. A value of upper-roman causes the items to be ordered using upper-case roman letters. Setting values of either lower-alpha or upper-alpha causes the items to be listed alphabetically. Unlike the HTML TYPE attribute, any of these nine values can be used in Internet Explorer with both ordered (<OL>) and unordered (<UL>) lists. Netscape Navigator 4 provides partial support for this attribute; it allows the values decimal, lower-roman, upper-roman, lower-alpha, and upper-alpha for ordered lists and disc, circle, square, and none for unordered lists.

Code Listing 14-5.

<HTML>
<HEAD>
<TITLE>Listing 14-5</TITLE>
</HEAD>
<BODY>
<UL>
Each of the following LI tags has the CSS attribute
<I>list-style-type</I> set to the specified value.
  <LI STYLE="list-style-type:disc">disc
  <LI STYLE="list-style-type:circle">circle
  <LI STYLE="list-style-type:square">square
  <LI STYLE="list-style-type:none">none
  <LI STYLE="list-style-type:decimal">decimal
  <LI STYLE="list-style-type:lower-roman">lower-roman
  <LI STYLE="list-style-type:upper-roman">upper-roman
  <LI STYLE="list-style-type:lower-alpha">lower-alpha
  <LI STYLE="list-style-type:upper-alpha">upper-alpha
</UL>
</BODY>
</HTML>

Click to view at full size.

Figure 14-5. You can control the list marker by using the list-style-type CSS attribute.

With the list-style-image CSS attribute, you also have the option of using your own images for markers. Code Listing 14-6 demonstrates this attribute, and Figure 14-6 displays the results.

Code Listing 14-6.

<HTML>
<HEAD>
<TITLE>Listing 14-6</TITLE>
</HEAD>
<BODY>
<UL>
The following LI tags have list-style-image specified.
  <LI STYLE="list-style-image:url(one.gif)">url(one.gif)
  <LI STYLE="list-style-image:url(img/two.gif)">url(img/two.gif)
  <LI STYLE="list-style-image:url(img/three.gif)">url(img/three.gif)
  <LI STYLE="list-style-image:none">none
</UL>

<HR>
<UL STYLE="list-style-position:outside">
  <LI>This demonstrates how setting a list-style-position
    of outside affects the way that text will wrap.
  <LI>This demonstrates how setting a list-style-position
    of outside affects the way that text will wrap.
</UL>

<UL STYLE="list-style-position:inside">
  <LI>This demonstrates how setting a list-style-position
    of inside affects the way that text will wrap.
  <LI>This demonstrates how setting a list-style-position
    of inside affects the way that text will wrap.
</UL>
</BODY>
</HTML>

Click to view at full size.

Figure 14-6. The list-style-image attribute sets an image as an item marker, and the list-style-position attribute controls text wrap.

The first list in Code Listing 14-6 contains four items. The first three items use list-style-image and associated url values to point to particular graphics. The first item points to url(one.gif), which uses the file named one.gif from the same folder as lst14-6.htm. The second item points to url(img/two.gif), which uses the file named two.gif from a subfolder of the folder that contains lst14-6.htm. The list-style-image attribute also accepts the value none, which simply allows the default list marker to display. Netscape Navigator does not support this attribute.

Code Listing 14-6 also demonstrates the use of the list-style-position attribute, which controls how the text in a list item wraps relative to the list item marker. The default for this attribute is outside, which causes each new line of text to wrap to the right of the marker. The final list item in Figure 14-6 shows how text with a list-style-position of inside behaves. This position results in a more compressed list because the text wraps under the marker.

So far, we have used dynamic styles to set up static Web pages. In the next chapter, we will investigate how to use the script to change the styles of elements after the page has been displayed, making these styles truly dynamic.


Chapter 15 -- Scripting Dynamic Styles

 Chapter 15

Scripting Dynamic Styles

With dynamic styles in Microsoft Internet Explorer versions 4 and later, an element's formatting can be changed at any time with script—a capability that has far-reaching implications. For example, using dynamic styles in your Web page gives you the ability to:

  • Change the size, weight, and even the font style of your text in response to a user's input

  • Expand and collapse outlines

  • Move items on the screen

Unfortunately, current versions of Netscape Navigator do not support dynamic styles in the same way as Internet Explorer, and once elements have been rendered on the screen they can be difficult or impossible to change. The examples in this chapter have been designed to degrade gracefully in browsers that do not support dynamic styles, such that even if a particular DHTML capability is not supported, error messages will not be displayed.


CSS and the Dynamic HTML Object Model

So far, we have seen how to use CSS attributes with style sheets and traditional HTML. Every HTML element that supports the STYLE attribute is represented internally by Internet Explorer as an object with a style child object. All CSS attributes are represented as properties of this style child object. In this chapter, we will learn how to use script to manipulate an object's style, just as we saw script used to control other aspects of objects in Part 2 of this book.

When you use scripting, you can access all CSS attributes through their corresponding properties in the Dynamic HTML Object Model. Sometimes an attribute and its corresponding property have slightly different names because the hyphen specified by CSS conventions is not allowed in the Object Model, where it could be incorrectly read as a minus sign. As a general rule, you can convert a CSS attribute to its Object Model equivalent by removing all hyphens from the attribute name and capitalizing any letter that originally followed a hyphen. For example, the CSS attribute background-image corresponds to the Object Model property backgroundImage, and the page-break-before attribute corresponds to the pageBreakBefore property.

Some CSS attributes have multiple representatives in the Dynamic Object Model. For instance, you can affect the CSS attribute background-position through script by using the backgroundPosition, backgroundPositionX, or backgroundPositionY property. (The latter two allow more specific control.) Table 15-1 lists all CSS attributes and their equivalent properties in the Dynamic Object Model.

Table 15-1 CSS Attributes and Corresponding Object Model Properties

CSS Attribute | Object Model Property
background | background
background-attachment | backgroundAttachment
background-color | backgroundColor
background-image | backgroundImage
background-position | backgroundPosition backgroundPositionX backgroundPositionY
background-repeat | backgroundRepeat
behavior | behavior
border | border
border-bottom | borderBottom
border-bottom-color | borderBottomColor
border-bottom-style | borderBottomStyle
border-bottom-width | borderBottomWidth
border-collapse | borderCollapse
border-color | borderColor
border-left | borderLeft
border-left-color | borderLeftColor
border-left-style | borderLeftStyle
border-left-width | borderLeftWidth
border-right | borderRight
border-right-color | borderRightColor
border-right-style | borderRightStyle
border-right-width | borderRightWidth
border-style | borderStyle
border-top | borderTop
border-top-color | borderTopColor
border-top-style | borderTopStyle
border-top-width | borderTopWidth
border-width | borderWidth
clear | clear
clip | clip
color | color
[no equivalent] | cssText
cursor | cursor
direction | direction
display | display
filter | filter
float | styleFloat
font | font
font-family | fontFamily
font-size | fontSize
font-style | fontStyle
font-variant | fontVariant
font-weight | fontWeight
height | height posHeight pixelHeight
ime-mode | imeMode
layout-grid | layoutGrid
layout-grid-char | layoutGridChar
layout-grid-char-spacing | layoutGridCharSpacing
layout-grid-line | layoutGridLine
layout-grid-mode | layoutGridMode
layout-grid-type | layoutGridType
left | left posLeft pixelLeft
letter-spacing | letterSpacing
line-height | lineHeight
list-style | listStyle
list-style-image | listStyleImage
list-style-position | listStylePosition
list-style-type | listStyleType
margin | margin
margin-bottom | marginBottom
margin-left | marginLeft
margin-right | marginRight
margin-top | marginTop
overflow | overflow
overflow-x | overflowX
overflow-y | overflowY
padding | padding
padding-bottom | paddingBottom
padding-left | paddingLeft
padding-right | paddingRight
padding-top | paddingTop
page-break-after | pageBreakAfter
page-break-before | pageBreakBefore
position | position
ruby-align | rubyAlign
ruby-overhang | rubyOverhang
ruby-position | rubyPosition
table-layout | tableLayout
text-align | textAlign
text-decoration | textDecoration textDecorationBlink textDecorationLineThrough textDecorationNone textDecorationOverline textDecorationUnderline
text-indent | textIndent
text-justify | textJustify
text-transform | textTransform
top | top posTop pixelTop
vertical-align | verticalAlign
visibility | visibility
width | width posWidth pixelWidth
word-break | wordBreak
z-index | zIndex

When you read or set (write) a property of the style object, you should use dot notation, which describes where an item fits in the Dynamic Object Model. The following tag, named MySpan, contains the STYLE attribute, which specifies the color blue for this SPAN element.

<SPAN ID="MySpan" STYLE="color: blue">Hello!</SPAN>

You can refer to this in the Dynamic Object Model by accessing the MySpan object, then its style subobject, and finally its color property. To do so, use dot notation as follows:

MySpan.style.color

You can use expressions such as this one to read the values of properties through the Object Model. For instance, if you want to assign the value of the color property of MySpan's style subobject to a variable named itsColor, use the following line of script.

itsColor=MySpan.style.color

Based on the initial HTML sample tag, the variable itsColor would be set to the value blue.

You can also use dot notation to change a property. For example, if you want to set the text color of MySpan to red, instead of blue, use this script:

MySpan.style.color="red"

Once this line is executed, the text changes color. Because the term red is not defined in the Object Model, it must be enclosed in quotation marks. Otherwise, it is treated as an undefined variable named red, and an error appears.

If you want to set the color property equal to a variable that has already been defined, you do not need to include quotation marks. For example, the following code changes the color of MySpan to red.

myVariable="red"
MySpan.style.color=myVariable

It is also unnecessary to use quotation marks around numbers. For example, the following code sets the width property of MySpan to 50.

MySpan.style.width=50


Using Script to Read and Set CSS Properties

Let's begin with a fairly basic example of both reading and setting CSS properties with script. Code Listing 15-1 demonstrates how you can use scripting to find out and change the current style settings of an object. Figure 15-1 shows how Internet Explorer initially displays the results of this code. In Figure 15-2 you can see the Alert dialog box that appears after the user clicks the text once. After clicking OK, the user sees a second Alert dialog box, which is displayed in Figure 15-3. Figure 15-4 shows the effect of clicking OK in the second Alert dialog box. This sample will not function in Netscape Navigator 4 (though no errors will occur) because Navigator does not support the onclick event on SPAN elements.

Code Listing 15-1.

<HTML>
<HEAD>
<TITLE>Listing 15-1</TITLE>
<SCRIPT LANGUAGE="JavaScript">
<!--
function changeIt(oClicked){
  oCS=oClicked.style
  alert("You clicked the element named "+oClicked.id+".")
  alert("It is "+oCS.fontWeight+". Click OK to change it.")
  if (oCS.fontWeight==`bold'){oCS.fontWeight=`normal'}
  else {oCS.fontWeight=`bold'}
}
//-->
</SCRIPT>
</HEAD>
<BODY>
<SPAN ID=MySpan STYLE="font-weight: bold; cursor: hand"
      onclick="changeIt(this)">
Click me!  Then click me again!
</SPAN>
</BODY>
</HTML>

Click to view at full size.

Figure 15-1. The initial display before the MySpan element is clicked.

Click to view at full size.

Figure 15-2. The first Alert dialog box.

Click to view at full size.

Figure 15-3. The second Alert dialog box.

Click to view at full size.

Figure 15-4. The final display after the font weight is changed.

Let's take a look at the framework of the page created in Code Listing 15-1. The SPAN element, which is named MySpan, has two CSS settings: its font-weight attribute is set to bold, and its cursor attribute is set to hand. Thus, the text in the element will be boldface by default, and the mouse pointer will change to a hand when it is resting over the element. The MySpan element also has an in-line onclick event handler, which specifies that the changeIt function should be called when the text is clicked. The keyword this is passed as an argument to the changeIt function, telling the function which item was clicked—in this case, the keyword this corresponds to the MySpan object.

The changeIt function contains the core of the sample. Because we will be using the style of the clicked object several times, we assign it to a variable. This makes for better performance and easier coding. The next line of code causes an Alert dialog box to display a text string. We created the string by concatenating three pieces of text: the words You clicked the element named, the value of the id property of the element that was clicked, and the period character. These are combined to appear in the dialog box as follows: You clicked the element named MySpan. Thus, we determined the name of the element that was clicked by reading its id property.

The next line also demonstrates how a property can be read. Every object in the Dynamic Object Model contains a style child object, which supports various properties such as fontWeight and cursor. The expression oCS.fontWeight refers to the fontWeight property of the object named oCS, which we have defined as the style child object of the item that was clicked. Thus, when the code is executed, oCS.fontWeight reads the current fontWeight setting of the item that was clicked. This line then produces an Alert dialog box telling you the font weight of the clicked item.

Next our function tests the font weight of the clicked item. If the item is bold, the function changes the weight by setting the item's fontWeight property to normal; otherwise, it sets the weight to bold. Notice that we assigned a value to a property simply by using dot notation to provide the name of the property and the particular value we wanted to assign.

By using script in Code Listing 15-1, we were able to alert the user to the current state of an item and change the font weight of that item depending on its current state. Next let's take a look at some more advanced examples.


Creating a Collapsible Outline

Outlines are a popular navigation tool on the Web. Code Listing 15-2 offers an example of using dynamic styles to create an outline that expands or collapses as the user clicks various headings. Figure 15-5 displays the outline in its initial, collapsed form, with only the section headings visible. Figure 15-6 shows that when the user clicks Section 2 the section expands to display the chapter listings. If the user clicks Section 2 again, it collapses back to its original form.

Code Listing 15-2.

<HTML>
<HEAD>
<TITLE>Listing 15-2</TITLE>
<STYLE>
  SPAN    {font-size: 18pt; cursor: hand}
  .on     {display: on}
  A       {text-decoration: none}
  A:hover {color: red; text-decoration: underline}
</STYLE>
<SCRIPT LANGUAGE="JavaScript">
<!--
// Set bSupportsDHTML to true for Internet Explorer 4 or later.
var bDoesDHTML = ( (navigator.userAgent.indexOf("MSIE") >= 0) &&
                   (navigator.appVersion.substring(0,1) >= 4) )

// Only hide menu items if browser supports DHTML.
if(bDoesDHTML){document.write("<STYLE>.off{display:none}</STYLE>")}

function doSection(secNum){
  if (bDoesDHTML){
    //display the section if hidden; hide it if it is displayed
    if (secNum.className=="off"){secNum.className="on"}
    else{secNum.className="off"}
  }
}
//-->
</SCRIPT>
</HEAD>
<BODY>
<SPAN onclick="doSection(Sec1)"><B>Section 1</B></SPAN><BR>
  <DIV CLASS="off" ID="Sec1">
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 1</A><BR>
  </DIV>
<SPAN onclick="doSection(Sec2)"><B>Section 2</B></SPAN><BR>
  <DIV CLASS="off" ID="Sec2">
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 2</A><BR>
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 3</A><BR>
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 4</A><BR>
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 5</A><BR>
  </DIV>
<SPAN onclick="doSection(Sec3)"><B>Section 3</B></SPAN><BR>
  <DIV CLASS="off" ID="Sec3">
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 6</A><BR>
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 7</A><BR>
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 8</A><BR>
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 9</A><BR>
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 10</A><BR>
  </DIV>
</BODY>
</HTML>

Click to view at full size.

Figure 15-5. The initial outline, in collapsed form.

Click to view at full size.

Figure 15-6. The outline dynamically expands when the user clicks Section 2.

NOTE
Code Listing 15-2 is much more complex than most examples in this book. Because this example is more likely than most to be copied and used on the Web, care has been taken to ensure that it will provide a good experience across browsers. This sample has been designed to provide full functionality in Internet Explorer versions 4 and later, and to gracefully degrade in other browsers. In Internet Explorer 3 and all existing versions of Netscape Navigator, the outline will display fully opened from the start. See Chapter 23 for further discussion of creating cross browser Web pages. See Chapter 24 for a more full-featured version of an expandable menu.

The script block in Code Listing 15-2 has three major parts. The first part tests to make sure that the browser in use is Internet Explorer version 4 or later. If it is, the bDoesDHTML variable is set to true.

The next piece of code will add a line of code to the document if bDoesDHTML is true. This line of code is a STYLE element that creates a new class, off. Notice that the parts of the outline that we want to hide use this class. These items will be hidden only for users of Internet Explorer version 4 and later because we define the off class only for these users.

The final part of code in the script block is the doSection function, which uses the display property to show and hide text parts of the outline. Each section heading has an onclick event handler. When the user clicks a section, the doSection function is called and is passed the name of the element to be shown or hidden. If the class of the item is off, it will be changed to on and the element will be shown. If it was previously on (or anything else), it will be turned off and the element will be displayed.

When an element's display property is set to none, the element is invisible and the page is drawn without allocating space for the element. Like the display property, the visibility property can hide an element, but when this property is set to hidden, the element still takes up space on the screen. Code Listing 15-3 illustrates what happens when you use the visibility property to hide items instead of the display property. In Figure 15-7, you can see how Internet Explorer initially displays this outline, with only the section headings visible. Notice that the page is drawn to allow space for the contents of the section (the chapter listing) to be displayed. Figure 15-8 shows the effects of clicking Section 2; the chapter listing is displayed in the space following the Section 1 entry. If the user clicks Section 2 again, the chapter listing disappears but the space remains.

Code Listing 15-3.

<HTML>
<HEAD>
<TITLE>Listing 15-3</TITLE>
<STYLE>
  SPAN    {font-size: 18pt; cursor: hand}
  .on     {visibility: on}
  A       {text-decoration: none}
  A:hover {color: red; text-decoration: underline}
</STYLE>
<SCRIPT LANGUAGE="JavaScript">
<!--
// Set bSupportsDHTML to true for Internet Explorer 4 or later.
var bDoesDHTML = ( (navigator.userAgent.indexOf("MSIE") >= 0) &&
                   (navigator.appVersion.substring(0,1) >= 4) )
// Only hide menu items if browser supports DHTML.
if(bDoesDHTML){document.write("<STYLE>.off{visibility:hidden}</STYLE>")}

function doSection(secNum){
  if (bDoesDHTML){
    //display the section if hidden; hide it if it is displayed
    if (secNum.className=="off"){secNum.className="on"}
    else{secNum.className="off"}
  }
}
//-->
</SCRIPT>
</HEAD>
<BODY>
<SPAN onclick="doSection(Sec1)"><B>Section 1</B></SPAN><BR>
  <DIV CLASS="off" ID="Sec1">
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 1</A><BR>
  </DIV>
<SPAN onclick="doSection(Sec2)"><B>Section 2</B></SPAN><BR>
  <DIV CLASS="off" ID="Sec2">
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 2</A><BR>
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 3</A><BR>
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 4</A><BR>
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 5</A><BR>
  </DIV>
<SPAN onclick="doSection(Sec3)"><B>Section 3</B></SPAN><BR>
  <DIV CLASS="off" ID="Sec3">
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 6</A><BR>
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 7</A><BR>
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 8</A><BR>
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 9</A><BR>
    &nbsp;&nbsp;&nbsp;<A HREF="generic.htm">Chapter 10</A><BR>
  </DIV>
</BODY>
</HTML>

Click to view at full size.

Figure 15-7. The initial outline, using the visibility property.

Click to view at full size.

Figure 15-8. The outline is dynamically filled in when the user clicks Section 2.

NOTE
Code Listings 15-2 and 15-3 also demonstrate two other useful applications of CSS. Setting the cursor CSS attribute to hand for SPAN elements will make the mouse pointer change to a hand when it is positioned over the section headings. Additionally, note that A has text-decoration set to none and A:hover is set to appear red and underlined. This means that anchors do not appear underlined until the mouse passes over them, at which point they will display as red and underlined.


Creating Movement on the Screen

Dynamic styles allows you to precisely position objects at specific locations on the screen. By changing the properties that specify location, the objects can be moved, as demonstrated in Code Listing 15-4. Figure 15-9 below shows the initial display in the Internet Explorer window. Moving the mouse on the screen causes the SPAN elements to move around on the page; Figure 15-10 presents only one possible state. (The dynamic movement that this code creates on the Web page is difficult to represent in an illustration. To appreciate what this code does, run chap15\lst15-4.htm on the companion CD.)

Code Listing 15-4.

<HTML>
<HEAD>
<TITLE>Listing 15-4</TITLE>
<STYLE>SPAN {position:absolute}</STYLE>
<SCRIPT LANGUAGE="JavaScript">
function moveSpans(){
  Span1.style.top=15
  Span2.style.posTop=Span2.style.posTop+1
  Span3.style.left=10
  Span4.style.top=window.event.y
  Span5.style.posLeft=window.event.x
  Span6.style.pixelTop=window.event.x
  Span6.style.posLeft=window.event.y
}
</SCRIPT>
</HEAD>
<BODY onmousemove="moveSpans()">
<SPAN ID="Span1" STYLE="top: 0; left: 0">First Span</SPAN>
<SPAN ID="Span2" STYLE="top: 50; left: 50">Second Span</SPAN>
<SPAN ID="Span3" STYLE="top: 100; left: 100">Third Span</SPAN>
<SPAN ID="Span4" STYLE="top: 150; left: 150">Fourth Span</SPAN>
<SPAN ID="Span5" STYLE="top: 200; left: 200">Fifth Span</SPAN>
<SPAN ID="Span6" STYLE="top: 250; left: 250">Sixth Span</SPAN>
</BODY>
</HTML>

Click to view at full size.

Figure 15-9. The Web page before the user moves the mouse.

Click to view at full size.

Figure 15-10. One possible example of a Web page after the user moves the mouse.

Code Listing 15-4 shows the effect of changing the properties that control the position of an element. All the SPAN elements on the page have their position property set to absolute, which allows us to specify exact pixel locations for their initial positions. To set these locations, we used the top and left properties.

NOTE
You can use many different properties to specify position—top, posTop, pixelTop, left, and posLeft, to name a few. Each property is useful in particular situations. You can find a full description of these properties on the SBN Workshop Web site and on the CD that accompanies this book. On the CD, go to Workshop (References); DHTML, HTML & CSS; CSS, and then CSS Attributes Reference. To get to the online version, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm, or open the file named MSDN_OL.htm on the companion CD and choose CSS Attributes Reference.

The BODY element in Code Listing 15-4 has an onmousemove event handler, which calls the moveSpans function every time the mouse moves over the body region or, in other words, every time the mouse moves anywhere on the page. This function specifies how the position of each SPAN element should change as the mouse moves. Span1 moves vertically to a location 15 pixels from the top of the screen and then stays there. As the mouse moves, Span2 constantly drops to a location 1 pixel lower (because the value of its posTop property is being incremented by 1 for each pixel that the mouse moves, in any direction). Span3 moves horizontally to a location 10 pixels from the left of the screen and remains there. (To return the window to its initial state, press the F5 key.) Because Netscape Navigator 4 does not support the onmousemove event handler on the BODY element, it never calls the moveSpans function or attempts to change an element's position on the screen.

The next three SPAN elements change their positions relative to the position of the mouse. The window.event.x and window.event.y properties specify the current mouse position. Span4 moves vertically when the mouse moves vertically, while Span5 matches the horizontal moves of the mouse. Span6 moves vertically as the mouse moves horizontally, and it moves horizontally as the mouse moves vertically, which can lead to interesting behavior when the mouse is moved in circles.

An example of how dynamic styles can create changing movement on the screen can be found on the SBN Workshop Web site and on the companion CD in the folder workshop\author\dhtml\tutorial\asteroids\asteroids.htm. In roughly 600 lines of code, this example uses only dynamic styles, script, and a few images to create a fully functional version of the old arcade game Asteroids. Check it out—you will be impressed.

As you have seen in the past several chapters, dynamic styles lets you change everything from the color of text to the position of an element simply by changing conventional CSS attributes. The next chapters present additional ways to create exciting Web pages with multimedia and animations.


Chapter 16 -- Visual Filters and Transitions

 Chapter 16

Visual Filters and Transitions

Visual filters and transitions are multimedia features that create visual effects for text, images, and other objects without imposing long download times on the user. These powerful tools are applied through the filter CSS attribute in Microsoft Internet Explorer versions 4.0 and later. Currently, this attribute is not included in the official W3C CSS specification, and Internet Explorer is the only browser that supports it. This chapter shows you how to use filters and transitions individually and together and explains how to script them.


Overview

Filters change the appearance of an element. For example, filters can flip an image or a block of text horizontally on its axis. They can also give an image or text a directional fade or a shadow. Transitions are typically used to transform an element from one condition to another. These are similar to effects frequently seen on television; for example, one image or page changes into another through a dissolve effect or by wiping from left to right.

Both visual filters and transitions are applied with the filter CSS attribute. Implementing filters and transitions through styles offers several advantages over using script and special ActiveX controls or Java applets. Using styles makes programming easier and provides automatic backward compatibility to browsers that do not understand either the filter attribute or CSS as a whole. This compatibility is achieved because any CSS attributes that are not understood by a browser are ignored; therefore, even if a browser does not render the filter on an element, it will still display the element and should not crash or return errors. This technique is also used for DHTML Behaviors, which are discussed in Part 5.

Useful tools for generating filters and transitions include the following, which can be found on the companion CD in the folders as indicated.

Tool | Location on Companion CD
Filter Wizard | /workshop/samples/author/dhtml/filtwizard/filtwzrd.htm
Wave Filter Wizard | /workshop/samples/author/dhtml/wavewizard/wavewzrd.htm
Transitions Wizard | /workshop/samples/author/dhtml/overview/trnswzrd.htm

These tools should also be available from the online version of the SBN Workshop at microsoft.com/workshop.


Filters

The filter style allows for 14 visual effects, as described in the following table.

Filter | Visual Effect
Alpha | Sets the level of opacity, or transparency, of an object
Blur | Directionally blurs an object, creating a sense of movement
Chroma | Renders a particular color on an object transparent
DropShadow | Creates a copy of an object, with a specified directional offset, giving the appearance of a shadow
FlipH | Renders a horizontal mirror image of an object
FlipV | Renders a vertical mirror image of an object
Glow | Creates a luminescence around an object
Grayscale | Removes all color information from an object, rendering the object in grays
Invert | Reverses the hue, saturation, and brightness of an object, producing an effect somewhat like a photo negative
Light | Creates the impression of a light source being projected onto an object
Mask | Renders a transparent mask from an object
Shadow | Paints a silhouette of an object, with a specified offset, creating a shadow effect
Wave | Creates the appearance of waves on an object
X-ray | Displays only the outside border of an object

A filter is applied like any other style—through a STYLE attribute, a global style sheet, or a linked style sheet. The values for the filter attribute are composed of the name of the filter to be applied followed by a set of arguments that control the filter, placed in parentheses. Code Listing 16-1 shows how the blur filter is applied to a <DIV> tag to change the appearance of a line of text on the page. Figure 16-1 below demonstrates the results.

Code Listing 16-1.

<HTML>
<HEAD>
<TITLE>Listing 16-1</TITLE>
<STYLE>
  DIV {width: 100%;font: 32pt Arial bold}
</STYLE>
</HEAD>
<BODY>
<DIV STYLE="filter: blur(add=1, direction=135, strength=5)">
This DIV has the blur filter applied.
</DIV>
<DIV>
This DIV does not.
</DIV>
</BODY>
</HTML>

Click to view at full size.

Figure 16-1. Applying the blur filter to an object.

The global style sheet in Code Listing 16-1 sets the width of the object (explained in the next paragraph), the font size to large, the style to bold, and the type to Arial. The filter is then applied through an in-line style. It is given three arguments: add, direction, and strength. The add argument specifies whether the original text should appear with a shadow behind it, or whether the shadow should appear alone. Code Listing 16-1 specifies the value 1, which means that the original text is added to the shadow. A value of 0 would have excluded the original text. The direction argument specifies the direction of the blur, which is figured clockwise and based on the object's vertical axis. This argument accepts values in 45-degree increments. The possible values are 0 (up), 45 (up and to the right), 90 (right), 135 (bottom and to the right), 180 (bottom), 225 (bottom and to the left), 270 (the default, left), and 315 (up and to the left). The strength argument defines the length of the blur in number of pixels. Most filters have multiple arguments (sometimes referred to as parameters), and some have none at all. A full discussion of the arguments for each filter can be found on the SBN Workshop Web site. On the CD, go to Workshop (References); DHTML, HTML & CSS; CSS; CSS Attributes Reference; filter, and then click on the Visual Filter filter type. Online, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm, or open the file named MSDN_OL.htm on the companion CD and choose Visual Filter.

Visual filters can be used only with the following elements: BODY, BUTTON, DIV, IMG, INPUT, MARQUEE, SPAN, TABLE, TD, TEXTAREA, TFOOT, TH, THEAD, and TR. DIV and SPAN require that either the height or width CSS attribute be defined, or that the CSS position attribute be set to absolute.

Code Listing 16-2 demonstrates a number of the other filters in use. Figure 16-2, below, shows the resulting display.

Code Listing 16-2.

<HTML>
<HEAD>
<TITLE>Listing 16-2</TITLE>
</HEAD>
<BODY>
<IMG SRC="car.gif">
This image uses no filters.<BR>
<IMG SRC="car.gif"
     STYLE="filter:alpha(opacity=70, finishopacity=0, style=1)">
This image uses the alpha filter.<BR>
<IMG SRC="car.gif"
     STYLE="filter:flipv">
This image uses the flipv filter.<BR>
<IMG SRC="car.gif"
     STYLE="filter:glow(color=blue)">
This image uses the glow filter.<BR>
<IMG SRC="car.gif"
     STYLE="filter:chroma(color=red)">
This image uses the chroma filter.<BR>
<IMG SRC="car.gif"
     STYLE="filter:wave(strength=6, freq=4, lightstrength=25)">
This image uses the wave filter.<BR>
</BODY>
</HTML>

Code Listing 16-2 uses IMG tags rather than DIVs. The image used is a GIF of a car with transparent pixels around the car and in the windows. We applied the alpha, flipv, glow, chroma, and wave filters. Some of these filters have optional parameters that we did not take advantage of. For example, the alpha filter allows precise control over the fade effect by letting you specify a beginning and end location for the opacity and finishopacity.

Click to view at full size.

Figure 16-2. Other available visual filters.

Application Through Script

The Code Listings thus far have applied filters directly through in-line styles. Filters can also be applied to an object through the object model with script. Each element has a style child object, which in turn has a filter child object. A filter value can be assigned as follows:

    object.style.filter="glow(color=red)"

Code Listing 16-3 shows an example of assigning a style through script based on events happening on the page. Figure 16-3 shows the results.

Code Listing 16-3.

<HTML>
<HEAD>
<TITLE>Listing 16-3</TITLE>
<STYLE>
  DIV {width:100}
</STYLE>
<SCRIPT LANGUAGE="JavaScript">
function addFilt(oWhich){
  oWhich.style.filter="glow(color=red, strength=2)"
}
function removeFilt(oWhich){
  oWhich.style.filter=" "
}
</SCRIPT>
</HEAD>
<BODY>
<DIV onmouseover="addFilt(this)" onmouseout="removeFilt(this)">
Mouse over me!
</DIV>
<DIV onmouseover="addFilt(this)" onmouseout="removeFilt(this)">
Mouse over me!
</DIV>
<DIV onmouseover="addFilt(this)" onmouseout="removeFilt(this)">
Mouse over me!
</DIV>
<DIV onmouseover="addFilt(this)" onmouseout="removeFilt(this)">
Mouse over me!
</DIV>
</BODY>
</HTML>

Click to view at full size.

Figure 16-3. Applying filters dynamically through script.

When the page is first loaded, Internet Explorer displays the text without any special style or filter. When the user moves the mouse over any of the DIV elements, the function addFilt takes over and dynamically applies the glow filter to that DIV. When the pointer is moved away from the DIV element, the removeFilt function removes the filter. This simple example of dynamic filters shows how easy it is to add a lot of pizzazz and interactivity to an ordinary Web page. You can add multiple filters to a single object at one time, resulting in a more interactive and complex Web page. Code Listing 16-4, below, demonstrates this by applying both the glow filter and the wave filter to text. Figure 16-4 illustrates the results.

Code Listing 16-4.

<HTML>
<HEAD>
<TITLE>Listing 16-4</TITLE>
<STYLE>
  DIV {width:250;font-size:36}
</STYLE>
<SCRIPT LANGUAGE="JavaScript">
function addFilt(oWhich){
  oWhich.style.filter="glow(color=red, strength=5); wave(freq=3,
      lightstrength=50, phase=0, strength=2)"
}
function removeFilt(oWhich){
  oWhich.style.filter=" ";
}
</SCRIPT>
</HEAD>
<BODY>
<DIV onmouseover="addFilt(this)" onmouseout="removeFilt(this)">
Mouse over me!
</DIV>
<DIV onmouseover="addFilt(this)" onmouseout="removeFilt(this)">
Mouse over me!
</DIV>
<DIV onmouseover="addFilt(this)" onmouseout="removeFilt(this)">
Mouse over me!
</DIV>
<DIV onmouseover="addFilt(this)" onmouseout="removeFilt(this)">
Mouse over me!
</DIV>
</BODY>
</HTML>

Code Listing 16-4 has a few simple changes from the code in Code Listing 16-3. The font-size was increased in the global style sheet to make the effect easier to see. The wave filter was added to the doFilt function by including the filter name and its arguments on the same line as the glow filter. Notice that a semicolon and a space separate the filters. Without these characters, only the first filter listed will work properly. Because of these changes to the doFilt function, when the user places the mouse pointer over the text, the glow and wave filters are applied at the same time. You can string together as many filters as you like and apply them to an object, but as you might notice from Figure 16-4, this can affect readability.

Click to view at full size.

Figure 16-4. Applying multiple filters to an object.

Note that the line of code in Code Listing 16-4 that applies the filters has wrapped to two lines in this book's printed text. However, you should type in the code as a single line. An alternative to coding all the filters in one script command is to add each filter sequentially. For example, to combine the glow, flipv, and chroma filters, we could have used the following code:

    oWhich.style.filter=("glow(color=red, strength=5); " +
                         "flipv(); " +
                         "chroma(color=black)")

Now let's get a little fancy with filters. Code Listing 16-5 applies a random colored glow and the wave filter to the text when the onmouseover event occurs. As long as the mouse pointer remains positioned over the text, the value of the wave filter's phase argument is changed over time. This technique creates the effect of viewing the text underwater. When the mouse pointer is moved away from the text, the filters are removed.

Code Listing 16-5.

<HTML>
<HEAD>
<TITLE>Listing 16-5</TITLE>
<STYLE>
  DIV {width: 250; font-size: 24pt; font-weight: bold;}
</STYLE>
<SCRIPT LANGUAGE="JavaScript">
var count=0; var thePhase=0; var aniOn=0;
var colorList=new Array("red", "blue", "green");
//this function changes the wave filter phase
function anitext(){
  thePhase=(thePhase + 10)
  MyDiv.filters[0].phase=thePhase
  // the next line causes this function to be called 5 times/second
  oTO=window.setTimeout("anitext()",0200,"JavaScript")
}

function doFilt(){
  MyDiv.style.filter="wave(add=0, freq=3, lightstrength=50, phase=0, strength=2, enabled=1); "
  rndNum=Math.floor(Math.random() * 3)
  MyDiv.style.filter+="glow(color=" + colorList[rndNum] + ", strength=5)"
  anitext()
}

function removeFilt(){
  window.clearTimeout(oTO)
  MyDiv.style.filter=" "}
</SCRIPT>
</HEAD>
<BODY>
<DIV ID="MyDiv" onmouseover="doFilt()" onmouseout="removeFilt()">
Demonstration of dynamic filters
</DIV>
</BODY>
</HTML>

Several new techniques are demonstrated in Code Listing 16-5. In the doFilt function (called when the mouse passes over the text), a random number from 0 to 3 is generated. This is used to pick a random color out of an array, which is then applied by a glow filter. The anitext function is then called. This function increments the value of the wave filter's phase argument by 10 and then sets a timer that calls the same function again, after 200 milliseconds (one fifth of a second) have passed. These changes continue in an endless loop until all the effects are turned off by the removeFilt function, called by the DIV's onmouseout handler. This function also removes the timer, preventing the anitext function from being called continuously.

These techniques demonstrate only a few of the ways filters can be used to add effects to objects. Objects on your Web page can also be made interactive with transitions.


Transitions

Whereas filters are used to apply formatting to an object that already appears on the screen, transitions are used to affect how an object is displayed on, or disappears from, the screen. Internet Explorer supports two basic types of transitions: the blend transition and the reveal transition. Blend transitions work by fading an object into or out of visibility. Because of this functionality, the blend transition has only one argument, duration, which states how long the fade-in or fade-out cycle will take. The reveal transition uses one of several effects to hide one object and reveal another. Table 16-1 presents a list of the transition effects supported and the numeric values used to represent them in code.

Table 16-1 Transition Effects and Their Numeric Values

Transition Effect | Numeric Code | Transition Effect | Numeric Code
box in | 0 | random dissolve | 12
box out | 1 | split vertical in | 13
circle in | 2 | split vertical out | 14
circle out | 3 | split horizontal in | 15
wipe up | 4 | split horizontal out | 16
wipe down | 5 | strips left down | 17
wipe right | 6 | strips left up | 18
wipe left | 7 | strips right down | 19
vertical blinds | 8 | strips right up | 20
horizontal blinds | 9 | random bars horizontal | 21
checkerboard across | 10 | random bars vertical | 22
checkerboard down | 11 | random | 23

Code Listing 16-6 below demonstrates bringing an image onto a page with a simple dissolve transition. Figure 16-5 captures the effect in progress.

Code Listing 16-6.

<HTML>
<HEAD>
<TITLE>Listing 16-6</TITLE>
<SCRIPT FOR="window" EVENT="onload" LANGUAGE="JavaScript">
  flower.filters.item(0).apply()
  flower.style.visibility="visible"
  flower.filters.item(0).play()
</SCRIPT>
</HEAD>
<BODY>
<!--
  transition 12 is "random dissolve"
  Change transition value for different effects
-->
<IMG ID="flower" SRC="flower.gif";
     STYLE="visibility: hidden;
            filter: revealtrans(duration=2.0, transition=12)">
</BODY>
</HTML>

Click to view at full size.

Figure 16-5. Partway through the transition of the image into visibility.

In the <IMG> tag in Code Listing 16-6, we set the image to be invisible initially (that is, we set its visibility property to hidden) because we want it to become visible over time. Also notice in the <IMG> tag that the transition is defined in the STYLE attribute as a filter. The duration argument specifies the number of seconds the transition should take to complete, and the transition argument specifies which transition to use (indicated in the previous chart by the numeric value assigned a particular transition).

When the page loads, the script block in the HEAD of the document is executed and performs three actions on the image object. Understanding this code is key to understanding transitions. For a transition to work, there must be a change in the state, or condition, of the object. In this case, the image object's initial state has been set to invisible. The first line of the script applies the filter that we defined in the <IMG> tag to the image. It does not actually execute the transition at this point because we have not yet specified the target state, which in this case is visibility. The target state is specified in the next line, which states that we want the image to become visible. The last line calls the play method, which actually executes the transition and causes the image to fade in.

Code Listing 16-7 allows the user to cycle through all 24 reveal transition effects by clicking a button at the bottom of the page. Figure 16-6 below shows one of the transitions in progress.

Code Listing 16-7.

<HTML>
<HEAD>
<TITLE>Listing 16-7</TITLE>
<SCRIPT LANGUAGE="JavaScript">
var curVal=0;
//put all the names of the reveal transitions in an array
var tNames=new Array("Box In", "Box Out", "Circle In",
      "Circle Out", "Wipe Up", "Wipe Down", "Wipe Right",
      "Wipe Left", "Vertical Blinds", "Horizontal Blinds",
      "Checkerboard Across", "Checkerboard Down",
      "Random Dissolve", "Split Vertical In", "Split Vertical Out",
      "Split Horizontal In", "Split Horizontal Out",
      "Strips Left Down", "Strips Left Up", "Strips Right Down",
      "Strips Right Up", "Random Bars Horizontal",
      "Random Bars Vertical", "Random");

function nextFilter(){
  ff=flower.filters.item(0)

  if (ff.status!=2) {
    flower.style.visibility="hidden"
    ff.transition=curVal
    ff.apply()
    flower.style.visibility="visible"
    ff.play()

    window.status="Transition " + (curVal) + " " + tNames[curVal]
    nextBtn.value=("Next Transition is " + tNames[curVal+1])
    if (curVal==23){curVal=0}
    else{curVal=curVal + 1}
  }
}
</SCRIPT>
</HEAD>
<BODY>
<IMG ID="flower" SRC="flower.gif";
     STYLE="visibility: visible;
            filter: revealtrans(duration=2.0, transition=1)">
<P>
<INPUT TYPE=button ID=nextBtn onclick="nextFilter()"
       VALUE="Next Transition is Box In">
</BODY>
</HTML>

Figure 16-6. One transition effect being applied to the flower image.

Each time the button is clicked, the nextFilter function is called. This function first checks the status of the transition to make sure that no other effect is in progress. If none is, the image is hidden. The transition is then changed to the variable curVal and applied to the image. Then the image is reset to visible, and the transition is played. The transition number (curVal) is incremented every time the button is clicked and loops back to 0 when it reaches the number 23. Information about the current transition is written to the status bar of the browser through the use of window.status, and information about the next transition is put into the button.


Combining Effects

Transitions and filters can be combined to create some unique effects. To combine different effects, simply add them as filter arguments in the STYLE attribute, as shown in Code Listing 16-8. In Figure 16-7, you can see how the image of a car looks when the random dissolve and circle out transitions are applied along with the shadow filter.

Code Listing 16-8.

<HTML>
<HEAD>
<TITLE>Listing 16-8</TITLE>
<SCRIPT FOR=window EVENT=onload LANGUAGE="JavaScript">
  car.filters.item(0).apply()
  car.filters.item(1).apply()
  car.style.visibility="visible"
  car.filters.item(0).play()
  car.filters.item(1).play()
</SCRIPT>
</HEAD>
<BODY>
<IMG ID="car" SRC="car.gif"; STYLE="visibility: hidden;
     filter: revealtrans(duration=2.0, transition=12)
             revealtrans(duration=2.0, transition=3)
             shadow(color=gray, direction=135)">
</BODY>
</HTML>

Click to view at full size.

Figure 16-7. A combination of the random dissolve and circle out transition effects with the shadow filter.

In Code Listing 16-8, we used two transition effects and one filter. Notice that each additional transition effect needs to be applied and played individually. It is possible to override the duration argument specified in a particular transition by providing a number as an argument for the play method in the script. For example, to change the circle out transition so that it completes in four seconds instead of two, simply change the last line of the script code to car.filters.item(1).play(4).

Interpage Transitions

The preceding examples have covered how to use transitions with elements on one page. Internet Explorer also provides a mechanism that allows you to apply transition effects when moving from one page to another. These interpage transitions can be used when either entering or exiting a page.

Interpage transitions are accomplished with a <META> tag in the header region of the page, as shown in the next example. To see the transition take place, we need two pages, an initial page and a target page. Code Listing 16-9 sets up a simple initial page containing one image and one hyperlink, with a yellow background so that the transition is easier to see.

Code Listing 16-9.

<HTML>
<HEAD>
<TITLE>Listing 16-9</TITLE>
</HEAD>
<BODY BGCOLOR="yellow">
<A HREF="lst16-10.htm">Click here for an interpage transition</A>
<P>
<IMG SRC="magic.gif">
</BODY>
</HTML>

The hyperlink we set up in Code Listing 16-9 initiates a jump to the target page. The target page in this example is also simple, containing only one image. The code for the target page is shown in Code Listing 16-10; you can get an idea of what the transition looks like in Figure 16-8.

Code Listing 16-10.

<HTML>
<HEAD>
<TITLE>Listing 16-10</TITLE>
<META HTTP-EQUIV="Page-Enter"
      CONTENT="revealtrans(duration=3.0, transition=23)">
<META HTTP-EQUIV="Page-Exit"
      CONTENT="revealtrans(duration=3.0, transition=23)">
</HEAD>
<BODY>
<A HREF="lst16-9.htm">Click here for an interpage transition</A>
<P>
<IMG SRC="flower.gif">
</BODY>
</HTML>

Figure 16-8. An interpage transition.

Notice that the header region of Code Listing 16-10 contains two <META> tags, which control the details of the transitions. The first one specifies the event that will trigger the transition, in this case, the page-enter event, the duration of the transition, and the type of effect to use (a random transition, with a numeric value of 23). To see the transition, simply open Listing 16-9 (chap16\lst16-10.htm on the companion CD) and click the hyperlink to move to the target page. The second <META> tag in Listing 16-10 controls the transition out of the page by setting HTTP-EQUIV to Page-Exit.

Visual filters and transitions are an easy way to add interesting, low-bandwidth special effects to a page. In the next part of this book, we will take a look at additional ways, using both high-bandwith and low-bandwidth techniques, of adding multimedia and special effects to Web pages.


Chapter 17 -- Multimedia on the Web

 Chapter 17

Multimedia on the Web

On the Web, the term "multimedia" refers to everything from a moving graphic and background audio on a page to a full-blown, high-quality video feed. Because such a broad range of features fits into this category, many separate tools and solutions have been developed to play multimedia, and modern browsers provide a wide variety of multimedia options. This chapter is an overview of some types of multimedia. It covers common cross browser ways to use multimedia on Web pages, shows how to create media files, and offers guidelines for planning the use of media on your Web pages.


Overview

The general idea of multimedia is to give the user a more exciting experience than is offered by static text and graphics on a page. Some examples of multimedia include:

  • An animated logo

  • A news site offering video clips of broadcast news stories instead of simply text

  • A movie company posting movie previews to the Web

  • An online music store offering sample audio clips from its CD selection

  • An individual adding some favorite background audio to a personal Web page

  • A company training its employees through interactive online courses

Designing Web pages that use multimedia to do all these things while remaining efficient is a challenging task. One constant issue encountered when using multimedia is the lack of available bandwidth needed to transfer the sizable amount of information that makes up most multimedia files. Let's take a look at some of the major types of multimedia.

Audio and Video

Audio and video were the first types of multimedia to be made available over the Web. Both can be played either directly in the browser or outside the browser in their own windows. There are also a number of different options for distributing these large files. Some of these involve downloading the entire file before it is played, while others play the file while it is downloading, a technique known as streaming. This chapter covers some basic cross browser ways of adding sound and video to a page. Chapter 18 really delves into the subject with a discussion of some of the more powerful multimedia controls.

Multimedia Controls

A new approach to the bandwidth problem was introduced in Microsoft Internet Explorer 4 with the DirectAnimation Multimedia Controls. These controls (which are supported only in Internet Explorer) are designed to eliminate media files by simply transferring instructions to the browser that tell it how to create and display an object. In some cases, this provides a solution to the bandwidth problem. For example, a file containing a video of a rotating graphic would be many times the size of a file containing instructions that produce the same video effect using the DirectAnimation Multimedia Controls. Four DirectAnimation Controls ship with Internet Explorer:

  • The Structured Graphics control is used to create lightweight vector graphics that can be scaled or rotated in three dimensions.

  • The Sequencer control manages the timing and sequencing of events on the page.

  • The Path control positions the elements and directs where they move on the page over a set period of time.

  • The Sprite control allows for the addition of still or animated images to a page and offers control over the frame rate and playback.

See Chapter 19 for more information on these controls.

Other Types of Multimedia

Web browsers can also display a variety of other types of media files, including MacroMedia Flash and ShockWave, Virtual Reality Markup Language (VRML), and Math Markup Language (MathML). Because these formats are not core technology in browsers and creating them frequently requires third-party editing products that must be purchased, we will not delve into them in this text.

Macromedia Flash is one of the most commonly used types of alternative multimedia. It allows for the creation of everything from buttons with built-in sound effects to a complete multimedia presentation with audio, video, and line graphics. It has great support for vector (line-based) graphics and produces very small files. Playback of flash files is done with Flash player (free and available for all common browsers and included with Internet Explorer versions 4 and later). Creating these files requires an editing program that can be purchased from Macromedia. Learn more about Flash at www.macromedia.com.

ChromeEffects is a new set of features that enables high-quality multimedia to be sent over the Internet to users of Internet Explorer 5 or later who are using Microsoft Windows 98 or Microsoft Windows 2000 on modern machines. An example of a fairly simple ChromeEffects project would be a spinning cube that has different video streams and HTML pages playing on each face. Because ChromeEffects appeals to a more limited audience, it won't be covered in this book.


Playing Multimedia

Historically, playing audio and video depended on third-party products called plug-ins. As browsers matured, more and more of the functionality provided by multimedia plug-ins was incorporated into the browser itself. Unfortunately, this means that multimedia is one of the hardest areas to get backward compatibility in, since support varies from browser to browser and version to version.

The <EMBED> Tag

The most common method of adding sound to Web pages is with the <EMBED> tag. It can also be used to add video and is supported in both browsers, back through at least version 3. Listing 17-1 demonstrates a simple use of <EMBED> to add a sound to a page. Figure 17-1 shows what the sound control panel looks like in Internet Explorer. Figure 17-2 shows the contents of the same page displayed in Netscape Navigator.

Code Listing 17-1.

<HTML>
<HEAD>
<TITLE>Listing 17-1</TITLE>
</HEAD>
<BODY>
<EMBED SRC="music.wav"
       VOLUME="50"
       HEIGHT="60"
       WIDTH="145"
       AUTOSTART="true"
       ALIGN="left"
       HIDDEN="false"
       LOOP="true">
</EMBED>
</BODY>
</HTML>

Click to view at full size.

Figure 17-1. A sound control panel in Internet Explorer.

Click to view at full size.

Figure 17-2. The same content in Netscape Navigator 4.

Note that the page displays differently in Netscape Navigator and Internet Explorer. The appearance of the sound control panel is not the only difference in how the two browsers handle this tag. Each supports a number of attributes and features that the other does not, and some of the attributes shared between the two browsers have different defaults. Table 17-1 provides an overview of the different attributes supported.

Table 17-1 Function and Default States for <EMBED> Tag Attributes in Internet Explorer and Netscape Navigator

Attribute | Function and Default
ALIGN | Functions exactly the same as ALIGN for <IMG> tags
AUTOSTART | true or false. Controls whether media starts automatically. The default depends on the browser, platform (Macintosh or PC), and state of the HIDDEN attribute, so it is usually better to explicitly state the value you want for this attribute.
ENDTIME | Expressed in mm:ss. Specifies when the media track should stop. Navigator only.
HEIGHT | Specifies the height of the panel in pixels. Navigator might exhibit unpredictable behavior if this is not specified.
HIDDEN | true or false. Controls whether the panel is visible. A setting of true is valuable for creating background soundtracks to a page.
HREF | Set to a URL to make the panel a hyperlink. Internet Explorer only.
LOOP | true or false. Navigator supports numeric values that function like PLAYCOUNT does for Internet Explorer.
NAME | Gives a name to the control.
PLAYCOUNT | Specifies the number of times the media should be repeated. Internet Explorer only.
PLUGINSPACE | Specifies where to find any plug-in necessary to play the media. This should be unnecessary if you stick to standard formats, such as WAV and MID.
PLUGINURL | Specifies where to find any software necessary to install a plug-in specified in PLUGINSPACE. Navigator only.
SRC | The location of the file to be played.
STARTTIME | Expressed in mm:ss. Specifies where in the media file the control should start playing. Navigator only.
TARGET | Acts like the TARGET attribute of an <A> tag. Works only if HREF is also set. Internet Explorer only.
VOLUME | Sets the volume of the audio. Navigator only. Internet Explorer plays back the equivalent volume to a setting of 50.
WIDTH | Specifies the width of the panel in pixels. Navigator might exhibit unpredictable behavior if this is not specified.

Code Listing 17-1 embeds a sound track in the Web page. Video can be embedded instead in the page by simply changing the SRC attribute so that it points to a video file instead of an audio file. This is demonstrated in Code Listing 17-2. The results are displayed in Figures 17-3 and 17-4.

Code Listing 17-2.

<HTML>
<HEAD>
<TITLE>Listing 17-2</TITLE>
</HEAD>
<BODY>
<EMBED SRC="clouds.avi"
       VOLUME="50"
       HEIGHT="286"
       WIDTH="320"
       AUTOSTART="true"
       ALIGN="left"
       HIDDEN="false"
       LOOP="true">
</EMBED>
</BODY>
</HTML>

Click to view at full size.

Figure 17-3. A video control panel in Internet Explorer.

Click to view at full size.

Figure 17-4. The same content in Netscape Navigator 4 after the video is started.

When the page first loads in Netscape Navigator, you may notice the instructions Double-click to activate the embedded Video Clip in the bar at the bottom of the window. After these instructions are followed, the page contents display as shown in Figure 17-4. Note that the video control panel in Internet Explorer is the same as its audio control panel. This is not the case in Netscape Navigator. Also, Netscape Navigator 3 requires a plug-in to play the file. If the user does not already have a plug-in for playing video files, he or she will be prompted to download one from a central Netscape download location.

In Internet Explorer, the <EMBED> tag is one way of accessing the Microsoft Media Player control (also known as the Microsoft ActiveMovie Control), which provides all the audio and video functionality in Internet Explorer. Far more powerful and precise manipulation of the Media Player control can be accomplished by issuing commands to it directly through script. This will be covered in the next chapter.

Media in an External Window

The <EMBED> tag is used to embed a video or audio clip in a Web page. To play a movie (or audio) in an external window, you need to cause the browser to launch an external media player. This can be accomplished with several mechanisms, two of which follow.

Referencing Media with the Anchor Tag

If an anchor tag's HREF attribute references a media file, clicking that anchor will play the media file in the system's default media player, as demonstrated in Code Listing 17-3, below. When the Clouds hyperlink is clicked, both Internet Explorer and Netscape Navigator launch the Windows Media Player. It plays the movie in a separate window displayed in front of the browser, as shown in Figure 17-5, below. (It will launch a different player if another one is the system default.)

Code Listing 17-3.

<HTML>
<HEAD>
<TITLE>Listing 17-3</TITLE>
</HEAD>
<BODY>
<A HREF="clouds.avi">Click here to launch the Clouds video.</A>
</BODY>
</HTML>

Click to view at full size.

Figure 17-5. This technique plays the video in an external window.

You will notice that the Windows Media Player controls are very similar to those displayed by the <EMBED> tag in Internet Explorer. This is because Windows uses the same media player program for the <EMBED> tag, scripting the Media Player control, and playing regular media files. Each is just a different interface to Windows Media Player (available on the Start Menu under Programs/Accessories/Entertainment, at least on Windows 98).

Referencing Media with window.location Through Script

A second method, similar to the <A> tag method above, is to change the value of the location property of the window object to point to a media file. Listing 17-4 demonstrates this technique.

Code Listing 17-4.This will display the same type of external window as Code Listing 17-3.

<HTML>
<HEAD>
<TITLE>Listing 17-4</TITLE>
</HEAD>
<BODY>
<FORM>
<INPUT TYPE="button" VALUE="Click here to launch the Clouds video"
       onclick="window.location=`clouds.avi'">
</FORM>
</BODY>
</HTML>

In this case, we choose to use a button on a form to launch the movie because both Netscape Navigator and Internet Explorer support the onclick event on an INPUT of TYPE= "button" and can thus use one to launch a script.


Streaming Media

There are many different streaming solutions that allow a file to be played as it is being downloaded. At this point, the two most popular are the Microsoft NetShow player (also known as the Windows Media Player) and the RealNetworks RealPlayer. Free players exist for both Netscape Navigator and Internet Explorer on a number of different operating systems that play NetShow, RealAudio, and RealVideo media files.

You can find more information about coding for and creating files for the RealPlayer at www.real.com. Extensive information about NetShow can be found at microsoft.com/windows/windowsmedia and on the SBN Workshop on the companion CD and the Web. On the CD, see Workshop (References); Streaming & Interactive Media; Windows Media Technologies. To get to the online version, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm, or open the file named MSDN_OL.htm on the companion CD and choose Streaming & Interactive Media.

NetShow can stream audio, video, and other types of content. It consists of an Active Streaming Format (ASF) file, which contains media, and an optional ASX file that includes instructions on how to play the ASF file and how to download from alternate servers if a primary server is busy or unavailable. You can convert existing audio and video files to ASF files with free tools available from microsoft.com/ntserver/basics/netshowservices. Available tools include command-line and graphical video and audio file converters, ASF editing tools, and plug-ins and add-ons, which allow output to ASF from both Adobe Premiere and Microsoft PowerPoint.

NOTE
NetShow and ActiveMovie represent different technologies that have merged over time. At this point, most media in Windows (including files historically handled through NetShow and ActiveMovie) is handled through the Windows Media Player, which can play most files with the following filename extensions: .avi, .asf, .asx, .rmi, .wav, .ra, .ram, .rm, .rmm, .mpg, .mpeg, .m1v, .mp2, .mpa, .mpe, .mid, .rmi, .qt, .aif, .aifc, .aiff, .mov, .au, and .snd.

One advantage of NetShow files is that they allow embedding of nonmedia elements (such as standard script code, text, and special commands) in the streamed files. This technology can be used to:

  • Add closed captions to a video.

  • Create a multiframe Web page with a NetShow stream in one frame controlling the URLs of the other frames. This can be used to create a page in which a person is speaking live in one frame while a slideshow of his or her presentation occurs in another.

  • Embed anchors in the stream so that they take you to a different place on the Web each time the NetShow window is clicked.

  • Embed anchors in the stream so that clicking on the NetShow window at different times will take you to different predefined markers in the NetShow stream.

Although it is possible to embed the Windows Media Player in a page, it is more common to simply launch the video in an external window using the anchor method, described earlier in the chapter. Listing 17-5 demonstrates how to embed a NetShow stream and an anchor that launches an external player.

Code Listing 17-5.

<HTML>
<HEAD>
<TITLE>Listing 17-5</TITLE>
<script language="JavaScript">
// This code makes Netscape Navigator better able to use the player.
if ( navigator.appName == "Netscape" ){
  navigator.plugins.refresh()
  document.write("\x3C" + "applet MAYSCRIPT Code=NPDS.npDSEvtObsProxy.class" )
  document.writeln(" width=5 height=5 name=appObs\x3E \x3C/applet\x3E")
}
</script>
</HEAD>
<BODY>
Embedded Media Player <BR>
<!— Object tag is used by Internet Explorer —>
<OBJECT ID="MPlayer" width=160 height=112 type="application/x-oleobject"
     CLASSID="CLSID:22d6f312-b0f6-11d0-94ab-0080c74c7e95""
CODEBASR="http://activex.microsoft.com/activex/controls/mplayer/en/

nsmp2inf.cab#Version=5,1,52,701"
     STANDBY="Loading Media Player components...">
  <PARAM NAME="FileName" VALUE="keister.asx">
  <PARAM NAME="AutoStart" VALUE="true">
  <PARAM NAME="ShowControls" VALUE="false">
  <!—Embedded plug-in for Netscape —>
  <EMBED TYPE="video/x-ms-asf-plugin" WIDTH="160" HEIGHT="112"
PLUGINSPAGE="http://www.microsoft.com/windows/mediaplayer/download/

default.asp"
     FILENAME="keister.asx"
     SRC="keister.asx"
     CONTROLTYPE=0>
  </EMBED>
</OBJECT>
<P>
<A HREF="keister.asx">Start the Media Player in an external window.</A>
<P>
<A HREF="http://www.microsoft.com/windows/mediaplayer/download/">
Get the full version of the Media Player.</A>
</BODY>
</HTML>

Click to view at full size.

Figure 17-6. This technique plays embedded video or starts an external window.

Listing 17-5 displays an embedded video and two links. This particular video is a sample file from the NetShow Web site and was designed for delivery over a standard 28.8 modem connection. If the user has not yet downloaded the Media Player, it will load automatically in Internet Explorer because of the CODEBASE attribute. In Netscape Navigator, if the player is not available an icon indicating that it needs to be downloaded will display. When clicked, it will prompt the user to download the player from the location specified in the PLUGINSPAGE attribute.

NOTE
There are several good reasons not to use CODEBASE to autodownload the player. First, it downloads a "light" version of the player that does not include all the codecs that come with the full version of the Media Player. This means it might not be able to play all video formats. Second, the CODEBASE that is specified downloads a version for 32-bit Windows systems (Windows 98, Windows NT, and Windows 95). This version does not work on Macintosh, Windows 3.x, or UNIX systems (although versions do exist for these systems). Thus, on all pages that use NetShow, we recommend that you include a link to the Windows Media Player downloads page, as shown in the sample. Another option is to use browser sniffing (discussed in Chapter 23) to determine what browser and operating system are being used, and only use CODEBASE when appropriate.


Animated GIFs

Animated GIFs are the most common type of multimedia found on the Web and are supported in all modern browsers. A single GIF graphic can contain many images and can present them in sequence, like a movie. Code Listing 17-6 demonstrates the use of an animated GIF.

Code Listing 17-6.

<HTML>
<HEAD>
<TITLE>Listing 17-6</TITLE>
</HEAD>
<BODY>
<IMG SRC="airplane.gif"><BR>
This page demonstrates an animated GIF.
</BODY>
</HTML>

Click to view at full size.

Figure 17-7. A still shot of an animated GIF.

Note that the HTML is exactly the same if the GIF isn't animated. An <IMG> tag simply is given an SRC attribute. As long as this SRC attribute points to a graphic that is an animated GIF, the graphic will animate. The file airplane.gif is a sample file from Microsoft's GIF Animator. Creating an animated GIF requires a tool designed for such a task. Popular tools include the following:

Product | Available From | Notes
Alchemy Mind Works GIF Construction Set | mindworkshop.com/alchemy/alchemy.html | Very powerful, allows detailed control of file.
Microsoft GIF Animator | Part of Microsoft FrontPage and Image Composer. Version 1.0 is available from some shareware sites. Find out more at microsoft.com/imagecomposer/gifanimator/gifanin.htm | Simple to use, easy to apply palettes.
Right to Left Software Anamagic GIF | rtlsoft.com | Very good at optimizing a GIF for smallest size.
GIFBuilder | Available from many individual sites on the Web. Can be found through any major search engine. | Very popular tool available only for the Macintosh.
WWW Gif Animator | Shareware sites. | Highly rated, has an Internet Explorer_like interface.

NOTE
The Web is a dynamic place. As a result, some of the locations specified above might have changed by the time you read this. But there are many good sites for shareware and freeware files, including www.hotfiles.com, www.shareware.com, www.jumbo.com, www.tucows.com, and wuarchive.wustl.edu.

Many of these tools can also be used to create GIFs with transparent areas, which are used when overlaying images. In addition, many tools designed for other tasks can output animated GIFs, such as MacroMedia Flash.


Planning Multimedia

Using multimedia on the Web can be tricky. Without careful planning, you can end up with pages that take a long time to download, look or sound bad, or do not work at all. This section covers some important areas to consider when planning to use multimedia in Web pages.

Bandwidth

As mentioned earlier, the bandwidth available to your clients is a major consideration when designing a Web page. This is especially true for pages using multimedia elements. Audio and video files can be enormous; to use them effectively takes careful planning.

These days, Web pages are being delivered through a variety of mechanisms. While most pages are still delivered relatively slowly over the Internet, fast connections are becoming more common, and high-speed intranets are becoming the de facto standard for most corporations. CD-ROM is also a popular source for Web pages.

If using CD-ROM or an intranet for delivery, you might have considerably more bandwidth at your disposal than if you are targeting standard users on the World Wide Web. For example, many home users still access the Internet at 28.8 Kbps—that is, only 28.8 kilobits per second can be downloaded to the browser (and usually, a sizable fraction of that is lost to overhead, meaning only about 20 Kbps of actual data is transferred). A quad-speed CD-ROM drive (very slow by today's standards) can deliver 600 KBps (600 kilobytes per second), roughly 200 times the amount of data delivered by a modem connection. An average corporate network connection can deliver about 10 megabits per second (more than 1 MB per second), approximately 400 times as much data as an average modem connection is able to deliver. Some corporate networks deliver 100 megabit or even gigabit (1000+ megabit) and faster connections. Fast connections to the Internet are also becoming more and more popular. An ADSL (Asymmetric Digital Subscriber Line) connection typically ranges in speed from 256 Kbps to over 6 Mbps, and some cable modem connections are as fast as 30 Mbps. Files read from a hard drive are transferred anywhere from 5 to 50 megabits per second or more.

There are huge differences (up to several orders of magnitude) in the speeds used to access Web pages. Correspondingly, there are huge differences in multimedia performance because of its need to transfer relatively large amounts of data. The general rule of thumb is to base your work on the lowest bandwidth found in your audience. In other words, if the lowest bandwidth in the target audience is a 28.8 Kbps modem connection, pages should be designed around this limitation, even though other users in the audience might be using higher bandwidth connections. Another approach is to offer a choice between different qualities of multimedia, so that users with a faster connection can access a better version of the file.

Palettes

A palette is simply a specified list of colors. Most graphics and multimedia use some sort of palette. Restricting the number of colors in an image can both reduce file size and improve the appearance of a Web page on systems that display a limited number of colors. The most common situation in which a Web designer makes a choice between palettes is during the creation of GIF files, which all require a palette. The most common palette found in images and other media on the Web is known as the Web-safe palette. This is an 8-bit palette (meaning that there are 256 potential slots in the list of colors) that contains 216 colors and 40 unused entries. Of the 40 unused entries in the palette, 20 are reserved for use by the operating system. The remaining 20 can be used by a designer to add colors to the image that are not in the safe palette. Versions of the safe palette in both the Windows PAL and Adobe Photoshop ACT file formats can be found on the companion CD as \chap17\iesafe.pal and \chap17\iesafe.act. Note that you may find multiple versions of the safe palette on the Web. These different versions should all contain the same colors, though they might be listed in a different order.

Some video files also use a palette. Some perform much better when using a particular palette, while others can be set up to use the Web-safe palette. The palette selection is dependent upon which codec is used to create and play back the video. Codecs are described later in this chapter.

NOTE
The exact method used to apply the correct palette to an image depends on the image-editing software being used. The process is different for every application; you may need to consult your image editor's documentation. The process typically involves converting the bit depth of the image (referred to in some programs as the mode) from 24- or 32-bit to 8-bit and choosing the appropriate palette for this conversion.

The Best Media for the Job

Internet Explorer offers many options for media elements. But this flexibility can also make it difficult to choose the best media for a particular task. For example, suppose we want to include an animated image on a Web page. We could use an animated GIF, a video file, a structured graphic, or a MacroMedia Flash file. Before expending the time and effort to produce a media element, we need to decide which one best fits our needs. Let's look at an example of the decision-making process we might use to select an element.

Let's say that our goal is to include a quarter-page, two-dimensional image that appears to be rotating in three-dimensional space. Audio will not be needed. The page needs to work on a 28.8-Kbps modem connection to the Internet, and is targeted only at on-the-road sales staff of a particular company that has specified Internet Explorer as the corporate browser.

Based on that stated goal, we can assess the strengths and weaknesses of the approaches as follows:

  • An animated GIF would work, but we would need to create and piece together all the frames of the animation. Because the image is quarter-page, the GIF would probably be rather large.

  • At quarter-screen, a traditional video file would be extremely large, even if we used a very low frame rate. Video is sometimes the best option when it is necessary to tightly synchronize audio with images or animation, but in this case audio is not needed.

  • If we used a structured graphic, we would need to create the graphic only once, and we could then rotate it on the page using a simple script. The structured graphic file would be quite small, even at quarter-screen, and the download times would be much faster than most other options.

  • Flash files can be read by default in Internet Explorer 4 and later, and can be read in other browsers as well (though this usually requires downloading a Flash viewer). The files are typically very small, and the download size (like for structured graphics) is not dependent on the display size. The major problem with Flash files is that they require a separate application (that costs money) to create the file.

Based on ease of creation, fast download times, and the fact that the graphic needs to work only in Internet Explorer, the structured graphic is probably the best solution to this problem. If the original conditions had been slightly different, any of the other options might have proved to be better—a higher bandwidth might have allowed for the inclusion of video, and compatibility with Netscape Navigator would have weighted the decision more heavily in favor of Flash.

Some other considerations to keep in mind when planning media include:

  • How many other media elements are on the page? Typically, the more media elements on a page (even if the elements are small) the more performance will degrade. This is not only because of bandwidth constraints but also because most media is fairly taxing on the rest of the computer.

  • What creation tools are available? For example, to create a Flash file, you must have the Macromedia Flash application. To piece together a video sequence, you will probably need a video-editing tool like Adobe Premiere.

  • How many colors does the page need? Users with low-end machines may be able to see only 256 colors at a time. In deference to such users, you might not want to include images that need, for example, many variations of one color. At the very least, it is a good idea to test your pages in 256-color mode (also known as 8-bit). On a PC running Windows 95, Windows 98, and Windows NT 4 or later, you can set your color depth in the Control Panel for Display. On most Macintosh machines, you can set your color depth in the Control Panel for Monitors.

  • How much control do you need over each element? Each media type in Internet Explorer allows the content developer to control different properties. You should plan how much control you will need before deciding on the technology you want to use.


Creating Video and Audio for the Web

Creating high-quality audio and video for the Web can be a challenging process. It almost always requires third-party tools and the knowledge of how to use them. This section focuses on some of the general concepts behind media creation, and not on the specific techniques used in a particular editing product.

Creating Video

There are many different ways to get video onto your computer. You can buy Video capture cards, products that allow video from a camera, VCR, or other video source to be read onto a computer. Some TV tuner cards come with software that captures TV video. You can also buy CDs that contain video clips. Once video is on a machine, an editing tool such as Adobe Premiere can be used to modify it, mix it with other video, or add sound and professional effects. You can also use video-editing tools to build a video from scratch.

Digital video is frame-based. Traditional film works by moving still frames past a lens at a rapid rate, usually 24 frames per second. Computer video works on the same principle. The video player displays a series of still frames on the screen in succession. On a computer, however, the developer can control such details as the frame rate.

Video File Size

Video creates some of the largest files on the Web. A 1-minute video file can use as much space as the total text of dozens of full-length novels. Many factors affect video file size, including choice of codec, video dimensions, frame rate, color depth, and the quality of any included audio. Let's look at each factor to see how it can affect the performance of your video files.

CODECS For video to work on the average computer, it must be compressed when it is created and decompressed when it is played back. This is because the file for an average 24-bit image, 640 pixels by 480 pixels, is roughly 900 KB. This means that a 30-second video played at only 15 frames per second would use 450 images and would be 405 MB in size (approximately the size of 800 books, each containing 100,000 words). To play this video back, a computer would have to display 13.5 MB of data every second. This is too much for the average computer to handle, and these numbers represent thousands of times more capacity than that of a modem.

To solve this problem, most video files are compressed to reduce file size and improve performance. A codec (short for compressor decompressor) controls the type of compression and decompression to be used. Put simply, a codec allows video to be saved in a much smaller file by finding patterns in the video and not saving repetitive information. When the video is played back, the codec restores the pieces originally removed and re-creates the original video, or a reasonably close facsimile thereof, on the screen.

The codec that is chosen has a profound effect on the file size and quality of the video. Some of the codecs available include: Cinepak, Intel Indeo, RLE, Video 1, and MPEG. Some of these are included by default with the Windows Media Player. Different codecs should be used for different kinds of video. A detailed discussion of codecs is beyond the scope of this book, but generally, "lossy" formats, such as Intel Indeo, are better for video of "real-world" objects like trees and people, while "nonlossy" formats, like RLE, are better for animations of screenshots and video with a small number of colors. As with many techniques on the Web, experimentation may be the key to finding the best tradeoff between quality and file size.

NOTE
A word of warning: Because a codec governs both compression and decompression, the computer that requests your media file must use the same codec to decompress that you used to compress the file. If you use any nonstandard codecs, you will need to tell users where they can get a copy of the codec you used. The most standard codecs include RLE, MPEG, and Cinepak. A list of all the codecs available on a particular Windows 98 system can be found in the Control Panel for Multimedia, on the Devices tab, under Video Compression Codecs.

DIMENSIONS In video, the larger the picture dimensions, the more information the computer must display on the screen. That being the case, smaller video dimensions result in smaller file size and better playback. As a general rule, you should use the smallest video dimensions you can reasonably get away with. This is especially true on the Web. It is also important to understand that many video codecs work more efficiently if the video maintains a 4:3 aspect ratio; in other words, they are 4 pixels wide for every 3 pixels in height, or vice versa.

While 640 x 480 and 320 x 240 pixel videos are fairly common in games or on CDs, they produce very large files and are all but unusable on the Internet. Smaller sizes like 160 x 120 can work over the Net, but 120 x 80 or 80 x 60 usually work better.

FRAME RATE Frame rate, measured in frames per second (FPS), is one of the most important considerations when creating video, especially for low-bandwidth situations. Higher frame rates usually require more data to be displayed, and low bandwidth equals a low data rate. Television broadcast-quality video runs at 30 FPS. Unfortunately, you will not get your video transferred over the Internet at anywhere near that frame rate under any but the most favorable circumstances. A frame rate of 7 FPS is generally considered "rock bottom" for motion video. A good compromise is 10, 12, or 15 FPS, but any video with a frame rate below 7 FPS will look more like a slide show than a video. Some formats are less affected than others are by frame rate. Most properly optimized animated GIF files will not increase noticeably in size when the frame rate is increased. Unfortunately, GIFs also offer the least assurance that a video will actually display at the desired rate and offer no options of embedded synchronized audio.

COLOR DEPTH The number of colors used in a video is expressed as color depth (also known as bit depth). For most digital video, the optimal color depth is 24-bit, or "true color" (16.7 million colors). A somewhat common color depth for home computers, however, is still 8-bit or 256 colors. If a 24-bit video is played on an 8-bit monitor, the codec will dither the video to 256 colors. Dithering is the process of reducing a high-color image or video to a lower-color image or video by finding the closest match in the available palette of colors—with the result that parts of the images might not appear as originally intended.

Designers often develop a specific color palette for their content and may want to apply that palette to their video to ensure that it will look as expected, no matter where it is played. Several codecs, such as RLE and Video 1, allow the creator to specify a particular palette during the compression of a video. Interestingly enough, as a result of the way codecs work with colors, palletized video files (reduced to 256 colors) are frequently much larger than 24-bit video files (16.7 million colors).

AUDIO QUALITY You'll find the details of audio resolution in the next section. However, when considering video file size, you should also be aware of audio issues. Video files often contain audio content, and high-quality audio often results in larger video file sizes.

Creating Audio

Audio technology has improved dramatically since the advent of the multimedia computer. Great strides have been made in reducing file size and improving quality. We can only touch on some of the basics here, but you can learn a great deal more about digital audio from the audio-editing software documentation and from books on the subject. Two suggested titles are listed below.

The Art of Digital Audio by John Watkinson (Butterworth-Heinemann, 1994).

Principles of Digital Audio by Ken C. Pohlmann (McGraw Hill, 1995).

One measure of digital audio quality is resolution. Audio resolution consists of two parts: bit depth and frequency. Most audio editing tools allow you to set the bit depth and frequency of the audio you create. Generally speaking, the higher the numbers, the better the quality. CD quality audio has a bit-depth of 16, a frequency response of 44,100 Hz, and typically has two channels of audio, for stereo. Before compressing audio for use on the Web, it is often helpful to reduce it to a lower resolution, for example, to 8-bit, 22,050 Hz (or even 11,025 Hz), mono (single channel).

Audio Codecs

The audio compression scheme you use will have a dramatic effect on the final result. You can choose from among many codecs: PCM, Lernout & Hauspie, ADPCM, IMA ADPCM, MPEG layer 3—and the list goes on. There are no hard-and-fast rules about which codec to use, so you will need to experiment. You'll generally find a trade-off between the amount of compression provided and the resulting quality of the audio.

Audio Software

Compression is typically handled by sound-editing tools. Some popular tools include:

Product | Available From | Notes
Sound Forge | Sonic Foundry. Contact www.sonicfoundry.com for more information | Very flexible and powerful editing tool.
CoolEdit | Shareware sites. | Both a shareware and a commercial version of this product exist.

This chapter introduced the use of media on the Web. The next chapter will cover a range of more specific tools such as basic multimedia HTML tags, the Media Player (ActiveMovie) Control, and the Interactive Music Control.


Chapter 18 -- More Audio and Video Technologies

 Chapter 18

More Audio and Video Technologies

There are a number of additional audio and video features that have varied support in different browsers. Some of these, such as the <BGSOUND> tag, are simple to use while others, like scripting the Media Player and Interactive Music Controls, are more complex. This chapter takes a look at some of these tools.


The <BGSOUND> Tag

The <BGSOUND> tag is a very simple way to add sound to a Web page. Unfortunately, it is supported only by Internet Explorer. Code listing 18-1 demonstrates the use of the <BGSOUND> tag.

Code Listing 18-1.

<HTML>
<HEAD>
<TITLE>Listing 18-1</TITLE>
<BGSOUND SRC="music.wav" LOOP="infinite">
</HEAD>
<BODY>
This page demonstrates the use of the BGSOUND tag
</BODY>
</HTML>

The <BGSOUND> tag must be located in the HEAD of the document. Like an IMG element, BGSOUND requires the SRC attribute to specify the location of the media file. BGSOUND supports a number of different media types. The exact types supported vary by operating system and individual machine. Commonly supported types include WAV, MIDI, and (somewhat less commonly) MP3.

The BGSOUND element supports a number of different attributes. The LOOP attribute specifies the number of times the sound file should be repeated. It accepts standard numerical values. A value of infinite or -1 will cause the sound to repeat forever. The BALANCE attribute accepts values between -10000 and 10000, where negative values direct sound to the left speaker, positive values send sound to the right, and a value of 0 will center the audio. The VOLUME attribute will accept values between -10000 and 0, where (nonintuitively) 0 is the loudest.

NOTE
<BGSOUND> will not work on systems that have the Play sounds option unchecked. This option is found in Internet Options/Advanced/Multimedia in the Tools menu in Internet Explorer 5 and in the View menu in Internet Explorer 4.


The <IMG> Tag and DYNSRC Attribute

Internet Explorer is the only browser that supports the DYNSRC attribute of the <IMG> tag. DYNSRC can be used to point to an actual video file. This technique works only with AVI files and is not nearly as flexible as the OBJECT element technique (which we will examine later). It is quite easy to use, however, and effective for simple jobs. Listing 18-2 demonstrates the use of this type of <IMG> tag. Figure 18-1 shows the results.

Code Listing 18-2.

<HTML>
<HEAD>
<TITLE>Listing 18-2</TITLE>
</HEAD>
<BODY>
<IMG DYNSRC="clouds.avi">
</BODY>
</HTML>

Click to view at full size.

Figure 18-1. An <IMG> tag that uses the DYNSRC attribute.

The DYNSRC attribute functions exactly like the SRC attribute, but it is used to point to a video instead of a standard graphic file. Like the <BGSOUND> tag, <IMG> supports the LOOP attribute, which specifies the number of times the video should be repeated. A value of infinite or -1 will repeat the movie perpetually.

IMG elements provide only minimal support for audio and video. Internet Explorer 4 and later support the Media Player control, which is scriptable and gives far greater control over your media.


Adding Video with the Media Player Control

The Media Player control is almost always used to include video and audio in Web documents with Internet Explorer 4 and later. Because this control is built into Internet Explorer, there are no extra components for the user to download and install. The Media Player control supports many common media types, including AVI and QuickTime video, WAV and MIDI audio, and MPEG video and audio. Code Listings 18-3 through 18-6 demonstrate Internet Explorer_specific use of the Media Player control. However, a Netscape Plug-in is available that allows the use of the Media Player inside Navigator. Code Listing 18-7 demonstrates a cross browser technique.

NOTE
Internet Explorer 4 originally included the Microsoft ActiveMovie control. This control has been replaced by the Media Player control, which is more flexible than its predecessor.

Using the OBJECT Element

Although the Media Player control is used implicitly in the examples above through the use of an HTML tag, explicitly embedding the Media Player control with an OBJECT (or OBJECT and EMBED) element allows you to manipulate the control's properties in many more ways. Like other objects used directly within an HTML page (such as the multimedia controls discussed in Chapter 19), the Media Player control requires that you open and close the OBJECT tags (<OBJECT> and </OBJECT>) and include a CLASSID. The basic syntax is as follows:

<OBJECT CLASSID="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95">
</OBJECT>

Under most circumstances, it is useful to give the control a name with the ID attribute and to set some of the control's properties with <PARAM> tags between the opening and closing object tags. Code Listing 18-3 and Figure 18-2 show a basic example of using the Media Player control with some <PARAM> tags.

Code Listing 18-3.

<HTML>
<HEAD>
<TITLE>Listing 18-3</TITLE>
</HEAD>
<BODY>
<OBJECT ID="MPlyr" CLASSID="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95">
  <PARAM NAME="FileName" VALUE="clouds.avi">
  <PARAM NAME="AutoStart" VALUE="true">
</OBJECT>
</BODY>
</HTML>

Click to view at full size.

Figure 18-2. A basic use of the Media Player control.

<PARAM> tags typically have two attributes. NAME is used to specify the name of the property that we want to set. VALUE is the value we want to set the property to. The Media Player control has many properties, including FileName and AutoStart. We set the FileName property to the location of the file we want the Media Player to play and the AutoStart property to true, which causes the control to play the file automatically.

Properties can be set with either <PARAM> tags or directly through script using dot notation. For example, the script command MPlyr.ShowControls=true would have the same effect as <PARAM NAME="ShowControls" VALUE="true"> given that the control had the attribute ID="MPlyr". Code Listing 18-4 demonstrates setting properties through <PARAM> tags and through script. It also shows examples of how some of the Media Player control's methods are called.

Code Listing 18-4.

<HTML>
<HEAD>
<TITLE>Listing 18-4</TITLE>
</HEAD>
<BODY>
<OBJECT ID="MPlyr" CLASSID="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95"
        ALIGN="left" WIDTH="320" HEIGHT="312">
  <PARAM NAME="FileName" VALUE="clouds.avi">
  <PARAM NAME="AutoStart" VALUE="-1">
  <PARAM NAME="ShowDisplay" VALUE="-1">
  <PARAM NAME="ShowControls" VALUE="-1">
  <PARAM NAME="ShowTracker" VALUE="-1">
  <PARAM NAME="PlayCount" VALUE="100">
</OBJECT>

<INPUT TYPE=button VALUE="Hide Display"
      onclick="MPlyr.ShowDisplay=false">
<INPUT TYPE=button VALUE="Show Display"
      onclick="MPlyr.ShowDisplay=true">
<BR><BR>
<INPUT TYPE=button VALUE="Show/Hide Controls"
      onclick="MPlyr.ShowControls=(MPlyr.ShowControls==true?false:true)">
<INPUT TYPE=button VALUE="Show/Hide Tracker"
      onclick="MPlyr.ShowTracker=(MPlyr.ShowTracker==true?false:true)">
<BR><BR>
<INPUT TYPE=button VALUE="Play" onclick="MPlyr.Play()">
<INPUT TYPE=button VALUE="Stop" onclick="MPlyr.Stop()">
<INPUT TYPE=button VALUE="Pause" onclick="MPlyr.Pause()">

</BODY>
</HTML>

The OBJECT element in Code Listing 18-4 embeds the Media Player control in the page. We use the <PARAM> tags to set values for certain properties at design time—that is, we specify the value for each property as we write the HTML code. The user can modify the values of these properties at run time by clicking the buttons on the page. These buttons use script that dynamically changes some of the properties of the embedded control. For example, clicking the Hide Display button sets the value of the ShowDisplay property to false, turning off the video display. Clicking the Show Display button sets the value back to true, turning the display back on. The Show/Hide Tracker and the Show/Hide Controls buttons use the JScript ?: operator (discussed in Part 2) to combine both the show and hide actions into one button. The results of this code listing are shown in Figure 18-3.

Click to view at full size.

Figure 18-3. Using script to change a control's properties.

The Play, Stop, and Pause buttons each access a different method of the Media Player control to change the state of the control. Note that they are accessed just like methods in the DHTML Object Model, covered in Chapter 6.

There are many other properties available that can be scripted on the Media Player control. Some of the more useful ones are listed in Table 18-1.

Table 18-1 Media Player Properties

Property | Description
AnimationAtStart | Controls whether Media Player displays an animation while the content is being downloaded. (true/false)
AutoRewind | Controls whether Media Player automatically returns to the beginning of the selection when it reaches the end of the selection. (true/false)
AutoStart | Controls whether Media Player automatically starts playing the multimedia stream. (true/false)
Balance | Controls the left/right stereo balance of any audio. Values range from _10,000 to 10,000, with 0 being perfectly balanced.
Bandwidth | Contains the bandwidth of the current streaming media being played in bits per second. Read only.
BufferingCount | Indicates how many times the clip was buffered during playback. Read only.
BufferingProgress | Indicates the percentage of buffering completed. Read only.
BufferingTime | Indicates how much time will be allotted for buffering. Read only.
ClickToPlay | Controls whether clicking on the control toggles playback and pausing. (true/false)
CurrentPosition | Specifies the current position of the player in the multimedia file, in seconds.
ConnectionSpeed | Indicates the connection speed specified by the user during setup of the Media Player. Read only.
DisplayBackColor | Controls the display panel's background color.
DisplayForeColor | Controls the color of the text in the display panel's foreground.
DisplayMode | Controls whether the display panel shows the current position of the player in the media file in seconds (0) or frames (1).
DisplaySize | Controls the size of the video window. 0 is same as source, 1 halves the dimensions, 2 doubles them, 3 makes the video full screen, 4 allows custom sizing, 5 makes it 1/16th the screen size, 6 makes it 1/4 the screen size, and 7 makes it 1/2 the screen size.
Duration | Indicates the clip's playing time. Read only.
EnableContextMenu | Controls whether the right-click menu for the Media Player object is functional. (true/false)
ErrorCode | Contains the current error code, if any. Read only.
ErrorDescription | Contains a textual description of the current error, if any. Read only.
FileName | Specifies the name of the multimedia file to be played.
HasError | Indicates whether there is currently an error. (true/false) Read only.
ImageSourceHeight | Contains the height of the source media. Read only.
ImageSourceWidth | Contains the width of the source media. Read only.
LostPackets | Indicates the number of packets lost during playback of the current streaming media. Read only.
Mute | Controls whether sound will be played. (true/false)
PlayCount | Controls the number of times the file is repeated. A value of 0 repeats the file forever.
PlayState | Contains information about the current state of the player. 0 means the player is stopped, 1 paused, 2 playing, 3 waiting for stream to begin, 4 scanning forward, 5 scanning in reverse, 6 skipping to next marker, 7 skipping to previous marker, 8 the stream is not open. Read only.
Rate | A multiplier that controls the rate at which the media is played. A value of 1 is full-speed, a value of .75 would be three-quarters speed, and so on
ReadyState | Indicates the state of readiness of the Media Player control, based on how much of the media file has loaded. A value of 1 means that the FileName property hasn't even been initialized yet, 0 that the file is loading, 3 that the file is still loading but that there is enough to begin playing the files, and 4 that the file has been fully downloaded. The Run method cannot be called to play a movie unless ReadyState equals either 3 or 4.
SelectionEnd | Controls where Media Player should stop playing the file. Expressed in seconds, relative to the beginning of the file.
SelectionStart | Controls where Media Player should start playing the file. Expressed in seconds, relative to the beginning of the file.
ShowControls | Controls whether the Controls Bar is shown. (true/false)
ShowDisplay | Controls whether the Display panel is shown. (true/false)
ShowGotoBar | Controls whether the Goto Bar (containing any markers in the stream) is shown. (true/false)
ShowTracker | Controls whether the Track Bar is shown. (true/false)
SourceLink | Contains the path to the clip being played. Read only.
StreamCount | Contains the number of streams in the file. Read Only.
TransparentAtStart | Controls whether Media Player is transparent when media is not playing. (true/false)
Volume | Controls the volume. Ranges from -10000 (silence) to 0 (full volume).

There are many additional properties (not discussed here) that can be used to control the Media Player from within a Web page or even a C++ or Microsoft Visual Basic program. A full description of the Media Player properties can be found at the Microsoft DirectX site; go to microsoft.com/directx/dxm/help/mmp_sdk/default.htm, or link from the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm by choosing Media Player Properties.

Media Player also supports a number of events, including buffering, click, dblclick, disconnect, displaymodechange, endofstream, error, keydown, keypress, keyup, markerhit, mousedown, mousemove, mouseup, newstream, openstatechange, playstatechange, positionchange, readystatechange, scriptcommand, warning. One of the most useful of these events is readystatechange, because it indicates whether the player can play a file.

Code Listing 18-4 demonstrated the Stop, Play, and Pause methods. In addition to these, Media Player supports the AboutBox, Cancel, FastForward, FastReverse, GetCodecDescription, GetCodecInstalled, GetCodecURL, GetMarkerName, GetMarkerTime, GetMediaInfoString, GetMoreInfoURL, GetStreamGroup, GetStreamName, GetStreamSelected, IsSoundCardEnabled(), Next, Open, Pause, Play Previous, Stop, and StreamSelect methods. IsSoundCardEnabled() is very useful because it returns information about the ability of a user's machine to play audio. You can find more information about these methods and events on the DirectX site.

Sound

If a user's computer lacks a sound card or audio is unavailable for some other reason, there is a possibility that script errors might occur when trying to use sound. The Media Player control lets you test a system's audio capability and then take action based on the results. As an example, Code Listing 18-5 uses the IsSoundCardEnabled method to test for sound. As the code indicates, if no sound card is available, a warning such as the one in Figure 18-4 is displayed to the user.

This example represents a simple response to the sound test. You can make the response more sophisticated, for instance, by taking the user to another page or by displaying text when sound is not available.

Code Listing 18-5.

<HTML>
<HEAD>
<TITLE>Listing 18-5</TITLE>
<SCRIPT FOR="window" EVENT="onload" LANGUAGE="JavaScript">
  if(MPlyr.IsSoundCardEnabled()==true){MPlyr.Play()}
  else {
    alert("No sound capability available. Click OK to continue.")
  }
</SCRIPT>
</HEAD>
<BODY>
<OBJECT ID="MPlyr" WIDTH=0 HEIGHT=0
  CLASSID="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95">
  <PARAM NAME="FileName" VALUE="music.wav">
</OBJECT>
This page plays background audio if the computer is able to play sound,
and warns the user if the computer is not.
</BODY>
</HTML>

Click to view at full size.

Figure 18-4. A warning is displayed to the user if sound is not available.

The Media Player control also provides the ability to "layer" media, which allows you to play multiple media files at the same time and control each one through script. To demonstrate, let's take our music clip from the previous example and add another layer to it, as shown in Code Listing 18-6. We'll also add buttons, shown in Figure 18-5, that will control whether a layer is playing, and at what volume.

Code Listing 18-6.

<HTML>
<HEAD>
<TITLE>Listing 18-6</TITLE>
<SCRIPT LANGUAGE="JavaScript">
//this function toggles a sound layer
function jToggleSnd(WhichSnd, WhichBtn, strText){
  if (WhichSnd.PlayState=="2"){
    WhichSnd.Pause()
    WhichBtn.value=("Turn "+strText+" On")
  }
  else{
    WhichSnd.Play()
    WhichBtn.value=("Turn "+strText+" Off")
  }
}
</SCRIPT>
</HEAD>
<BODY>
<!-- this is the control that plays the music -->
<OBJECT ID="MPMusic" WIDTH=0 HEIGHT=0
        CLASSID="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95">
  <PARAM NAME="FileName" VALUE="music.wav">
  <PARAM NAME="AutoStart" VALUE="1">
  <PARAM NAME="PlayCount" VALUE="0">
</OBJECT>
<!-- this is the control that plays the voice -->
<OBJECT ID="MPVoice" WIDTH=0 HEIGHT=0
        CLASSID="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95">
  <PARAM NAME="FileName" VALUE="voice.wav">
  <PARAM NAME="AutoStart" VALUE="1">
  <PARAM NAME="PlayCount" VALUE="0">
</OBJECT>

<H3>Layering sound files with the Media Player control</H3><P>
<INPUT TYPE=button ID=voiceBtn VALUE="Turn Voice Off"
       onclick="jToggleSnd(MPVoice, this, `Voice')">
<INPUT TYPE=button ID=musicBtn VALUE="Turn Music Off"
       onclick="jToggleSnd(MPMusic, this, `Music')">
<P>
<INPUT TYPE=button VALUE="Reduce Voice Volume"
       onclick="if (MPVoice.volume > -9500){MPVoice.volume-=500}">
<INPUT TYPE=button VALUE="Increase Voice Volume"
       onclick="if (MPVoice.volume < -500){MPVoice.volume+=500}">
<BR>
<INPUT TYPE=button VALUE="Reduce Music Volume"
       onclick="if (MPMusic.volume > -9500){MPMusic.volume-=500}">
<INPUT TYPE=button VALUE="Increase Music Volume"
       onclick="if (MPMusic.volume < -500){MPMusic.volume+=500}">
</BODY>
</HTML>

Click to view at full size.

Figure 18-5. You can control sound layers with input buttons and script.

When the user opens the page we created in Code Listing 18-6, both sound files start to play. Each one has PlayCount set to 0 so that it repeats endlessly. The user can click the appropriate button to toggle each sound on or off. For further control over the layers, there are volume buttons for each layer.

NOTE
At this point, the Media Player does not support mixing multiple audio streams in Microsoft Windows NT 4. No script errors should result from Listing 18-6 in Windows NT, but only one stream will be audible.

Use of the Media Player in Netscape Navigator

A Netscape plug-in has been created that allows the use of the Media Player inside Netscape Navigator versions 3 and later. Code Listing 18-7 demonstrates a page in which the Media Player is accessible from both Netscape Navigator and Internet Explorer.

Code Listing 18-7.

<HTML>
<HEAD>
<TITLE>Listing 18-7</TITLE>
</HEAD>
<BODY>
<OBJECT ID="MPlayer"
        CLASSID="CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95"
        CODEBASE="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701" [must be part of previous line]
        STANDBY="Loading Microsoft® Windows® Media Player components..."
        TYPE="application/x-oleobject">
        <PARAM NAME="FileName" VALUE="clouds.avi">
        <PARAM NAME="AutoStart" VALUE="true">
        <EMBED NAME="MPlayer"
               TYPE="application/x-mplayer2"
               PLUGINSPAGE = "http://www.microsoft.com/Windows/Downloads/
Contents/Products/MediaPlayer/" [must be part of previous line]
               SRC="clouds.avi">
        </EMBED>
</OBJECT>
</BODY>
</HTML>

The Media Player is loaded by Internet Explorer with the <OBJECT> tag and by Navigator with the <EMBED> tag. Note that the <OBJECT> tag specifies an ID of MPlayer, and the <EMBED> tag uses a NAME of MPlayer. Programming the Media Player in Netscape Navigator is largely the same as in Internet Explorer. Though methods are used in the same way (for example MPlayer.Play() ), there are some differences in how events and properties are accessed. Extensive documentation on the Netscape Plug-in is available from microsoft.com/directx/dxm/help/mmp_sdk/mediaplayerpluginfornetscapenavigator.htm or from the MSDN Online Resource Page; see Media Player in Navigator.


Interactive Music Control

The Interactive Music Control is a way to add interactive music to your Web pages and use almost no bandwidth. It can work in concert with the Microsoft Synthesizer to provide high quality audio that is more controllable than MIDI, another popular format of audio file.

With the Interactive Music Control, you can specify many characteristics, including Style, Personality, Band, Motif, Transition, Length, Shape, and Activity Level of the music. These all have different effects. For example, Band specifies the type of instruments used, the volume, and the balance of the music. Shape controls sound intensity in terms of the number of instruments and their activity. Code Listing 18-8 demonstrates the Interactive Music Control in use.

Code Listing 18-8.

<HTML>
<HEAD>
<TITLE>Listing 18-8</TITLE>
<OBJECT ID="IMC" CLASSID="clsid:D2377D41-E6FD-11CF-8DCF-00AA00C01802"
        CODEBASE="http://activex.microsoft.com/controls/music/
IMSTUP21.CAB#version=2,1,0,14"> [must be part of previous line]
<PARAM NAME="Activity" VALUE="1">
<PARAM NAME="Length" VALUE="80">
<PARAM NAME="MaxCPU" VALUE="30">
<PARAM NAME="NumVoices" VALUE="10">
<PARAM NAME="Style"
       VALUE="http://www.microsoft.com/music/styles/DANCEMIX.STY">
<PARAM NAME="Personality"
       VALUE="http://www.microsoft.com/music/styles/POPDIA.PER">
<PARAM NAME="PlayImmediate" VALUE="1">
<PARAM NAME="Repeat" VALUE="1">
<PARAM NAME="Shape" VALUE="4">
<PARAM NAME="Transition" VALUE="1">
<PARAM NAME="UseSoftwareSynthesis" VALUE="0">
</OBJECT>
</HEAD>
<BODY>
This page demonstrates the Interactive Music Control.<P>
<FORM>
<INPUT TYPE="button" onclick="IMC.PlayMotif(`Synth Brass')"
       VALUE="Synth Brass">
<INPUT TYPE="button" onclick="IMC.PlayMotif(`Orch Hits')"
       VALUE="Orch Hits">
</FORM>
</BODY>
</HTML>

This listing requires a net connection to work, since it downloads two files from www.microsoft.com. This file demonstrates controlling the Interactive Music Control with PARAM tags and through script. When the control is first loaded, PARAM tags are used to specify which files to play and how to play them. The buttons use script to cause different motifs to be played interactively by the user.

Much more about the Interactive Music Control can be found at microsoft.com/music, including a complete language reference, samples, a tutorial, and information about potential ways to use the Interactive Music Control in Netscape Navigator.

Thus far, we've covered many variations on conventional audio and video. In the next chapter, you will find information about the DirectAnimation Multimedia Controls, which allow everything from sequencing of events to the creation of complex animations.


Chapter 19 -- DirectAnimation Multimedia Controls

 Chapter 19

DirectAnimation Multimedia Controls

Microsoft incorporated a number of special multimedia ActiveX controls into Microsoft Internet Explorer version 4 that are being carried forward in version 5. They are not currently directly supported by any version of Netscape Navigator. These features were designed to help Web developers create low-bandwidth multimedia that can be controlled both at Web page creation time and when the page is being displayed. Because the effects created with these controls are constructed and directly controllable through script, they allow a level of programming control that is not possible with other similar technologies, such as Macromedia Flash. In this chapter, we will examine the multimedia controls included with Internet Explorer and how they can be used to build exciting, media-rich Web pages.

The DirectAnimation multimedia controls are a set of four ActiveX controls that play different roles in presenting multimedia. They offer several advantages to content developers.

  • Unlike most ActiveX controls, the DirectAnimation controls do not have to be downloaded by the user because they are included with Internet Explorer.

  • The DirectAnimation controls are windowless—that is, they are not restricted to a particular rectangle in the browser, and they can interact with other elements on the page. For example, an object can be created with transparent areas through which you can see text and other objects on the page.

  • The DirectAnimation controls allow integration and animation of vector graphics as well as bitmap images.

The DirectAnimation controls include the Structured Graphics control, the Sequencer control, the Path control, and the Sprite control. More about these controls can be found by going to microsoft.com/directx/dxm and choosing the DirectAnimation link. Let's begin by looking at how to use the Structured Graphics control.


The Structured Graphics Control

The Structured Graphics control is an effective and versatile tool for adding lightweight graphics to a Web document. Structured graphics are vector-based (meaning that they are constructed out of a series of lines and curves, rather than pixel by pixel like a JPG or GIF image) and tend to have very small file sizes compared to conventional graphics.

The DirectAnimation controls, like other ActiveX controls, must be identified on the page. The basic syntax for using this control is as follows:

<OBJECT
  ID=ObjectID
  CLASSID="CLSID:369303C2-D7AC-11D0-89D5-00A0C90833E6"
  STYLE="height: xx; width: xx; [styleProperty: xx]">
  <PARAM NAME="PropertyName" VALUE="PropertyValue">
</OBJECT>

Let's examine each part of the code. Notice first that everything is enclosed in a set of <OBJECT></OBJECT> tags, an HTML mechanism for identifying a non-HTML item. The ID attribute gives the object a name so that it can be referenced easily by script. Although an ID is not necessary, you will probably find that an object is of limited use without one since it becomes more difficult to address through script.

Every ActiveX control has a unique CLASSID—a required identifier that tells the browser which exact type of object is being used. Fortunately, you don't need to memorize those long hexadecimal number sequences. The easiest way to code the correct CLASSID is simply to copy it from another page that uses that control. To help you get started, we have included a text file named da_id.txt in the chap19 folder on the companion CD that contains all the CLASSIDs for the DirectAnimation controls, along with their friendly names. Many of the HTML editing programs, such as Microsoft FrontPage, Microsoft Visual Interdev, and others make adding objects (and their CLASSIDs) to a page as simple as selecting a name from a list.

The STYLE attribute is not completely necessary either, but it is very useful. It can be used to set a height and width for the overall structured graphic object (independent of any shapes created inside it). It is important that you size a structured graphic to be large enough to hold any items you create inside it. For example, if the object is only 100 pixels wide but it holds a shape 300 pixels wide, the shape inside will be clipped. Any shapes created inside the structured graphic object are normally drawn starting at its center. Without planning for this, you might find a shape being clipped by the right and bottom edges of the structured graphic object. You can avoid this situation by using the ExtentHeight and ExtentWidth parameters, discussed later in this chapter. The STYLE attribute also can be used to position an object on the page or to set its z-index to put the object behind or in front of other elements.

The PARAM tags allow you to set values for many of the properties that affect a control. <PARAM> tags can also be used to call methods of a particular control. The name portion of the PARAM element refers either to a property name, such as HighQuality, or to a line number. The value portion indicates either the value assigned to the property or a particular method that should be used. These properties and methods are different for every object. Although many objects might use properties or methods of the same name, the effects often differ for each object.

Code Listing 19-1 demonstrates a simple structured graphics object that creates a square. Figure 19-1 displays the results.

Code Listing 19-1.

<HTML>
<HEAD>
<TITLE>Code Listing 19-1</TITLE>
</HEAD>
<BODY>
<OBJECT
  ID="square"
  CLASSID="CLSID:369303C2-D7AC-11D0-89D5-00A0C90833E6"
  STYLE="height: 102; width: 102">
  <PARAM NAME="Line0001" VALUE="SetLineColor(0,0,255)">
  <PARAM NAME="Line0002" VALUE="SetLineStyle(1,2)">
  <PARAM NAME="Line0003" VALUE="SetFillStyle(10)">
  <PARAM NAME="Line0004" VALUE="SetFillColor(0,0,255,255,196,196)">
  <PARAM NAME="Line0005" VALUE="Rect(1,1,100,100,0)">
  <PARAM NAME="ExtentTop" VALUE="0">
  <PARAM NAME="ExtentLeft" VALUE="0">
</OBJECT>
</BODY>
</HTML>

Figure 19-1. A simple square with a fading fill.

NOTE
Many methods and properties require the use of line numbers. These settings will be executed in the order of their line numbers. Order of execution can be important in many situations. A real-world example would be:

  1. Turn so that you are facing South.

  2. Extend your West arm.

  3. Turn so that you are facing North.

In this case, you would finish with your right arm extended. If Steps 1 and 3 had been reversed, you would finish with your left arm extended.

This code sample shows some of the basic techniques for creating your own structured graphics. (Methods for automatically generating structured graphics shapes from existing graphic files will be covered later in this chapter.) The first two <PARAM> tags are used to define the line that creates the square. The first <PARAM> tag defines the color of the line in red, green, and blue components, in that order. We have set the red and green to 0 (thus no red or green) and the blue to 255 (the maximum), so our surrounding line is blue. The second <PARAM> tag sets the style of the line. The value of 1 sets it to a solid line, while 0 would have meant no line and 2 a dotted line. The second number in the SetLineStyle method sets the width of the line. The next two <PARAM> tags set the type and color of fill used for the shape. The SetFillStyle method supports a number of different types of fills, shown in the table below. We used fill type 11 to give a radial gradient from pure blue to a light red.

Style | Number Equivalent
No Fill | 0
Solid | 1
Horizontal Hatch | 3
Vertical Hatch | 4
Forward Diagonal Hatch | 5
Backward Diagonal Hatch | 6
Cross Hatch | 7
Diagonal Cross Hatch | 8
Horizontal Gradient | 9
Vertical Gradient | 10
Radial Gradient | 11
Line Gradient | 12
Rectangular Gradient | 13
Shaped Gradient | 14

The next <PARAM> tag uses the Rect method to draw a rectangle. A rectangle is considered one of the basic shapes used to create structured graphics. These basic shapes are also known as primitives and are the building blocks for creating more complex images. The standard methods for creating primitives are listed in the following table.

Method | Description
Arc | Draws a circular arc or an elliptical arc.
Oval | Draws an ellipse.
Pie | Draws a wedge shape.
Polygon | Draws a closed polygon.
Polyline | Draws a segmented line.
Polyspline | Draws a smooth curve through a set of points.
Rect | Draws a rectangle.
RoundRect | Draws a rectangle with rounded corners.
Text | Draws text strings as structured graphics.

Each of these methods is used in a different way, due to the differences among shapes. You can find full descriptions of these methods at microsoft.com/directx/dxm/help/da/ref_cntrl/controls_oview.htm. You can also go to the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm and choose Structured Graphics Overview.

The final two <PARAM> tags set the ExtentTop and ExtentLeft properties. These are similar to the CSS properties top and left. Setting both of these to 0 causes the shape to be drawn starting from the top left of the structured graphics object. Similar properties include ExtentHeight and ExtentWidth, which set the height and width of the shape within the overall structured graphic object. They can be used only if ExtentTop and ExtentLeft have been set. Some of the other useful properties of the Structured Graphics control that you can set with <PARAM> tags and through script are included in this table.

Property | Description
CoordinateSystem | Controls whethery values start with 0 at the top of the page (default, value 0) or at the bottom of the page (value 1).
HighQuality | Turns antialiasing on (value 1) or off (default, value 0).
MouseEventsEnabled | Controls whether mouse events are processed on the shapes (value 1) or not (default, value 0).
PreserveAspectRatio | Controls whether a shape's ratio of height to width is maintained as it is scaled (value 1) or not (default, value 0).
SourceURL | Points the Structured Graphics control to use an external file for its parameters. Similar to pointing a script tag to a JS file.

Several additional properties of the control can be set only through script. These properties deal with interfacing the Structured Graphics control with its more capable relative, the DirectAnimation control, which will not be covered in this book due to its highly technical nature.

Creating Structured Graphics Easily

From the previous information, you can imagine that creating a complex structured graphic could entail using hundreds of <PARAM> tags in the correct sequence. Needless to say, this could be difficult. As of this writing, structured graphics are most easily created by converting Windows Metafiles, which use the WMF filename extension. Many commercial applications can create WMF graphics, including CorelDraw!, Adobe Illustrator, Microsoft PowerPoint, Harvard Graphics, and many more. Microsoft Office also includes a number of clip art images in the WMF format.

To use WMF files in your Web pages, you'll need to convert them to Structured Graphics. You can find the Windows Metafile Converter utility (Wmfcnv.exe) in the Tools folder on the companion CD. This tool converts Windows Metafiles to text files of <PARAM> tags used to define a structured graphic. To use it, simply open the WMF file you want to convert, set the options you prefer, and save the file. You will then have a text file that you can cut and paste into your Web documents or refer to with the SourceURL <PARAM> tag.

Advantages of Vector-Based Graphics

The two most popular forms of computer graphics are raster graphics and vector graphics. Raster graphics, the form used by most of the popular image formats such as BMP and GIF, are built pixel by pixel, with information about each pixel saved as part of the graphic. Vector graphics are built using a series of lines and curves. The information for these images is saved for each line or curve rather than for each pixel.

Unlike raster images, vector images can be resized, rotated, stretched, and manipulated in many ways while keeping the integrity of the original image. If you zoom in too far in a normal bitmap graphic, aliasing will occur and the edges of a shape will no longer appear smooth. To demonstrate the advantages of vector graphics, we'll need a more complex structured graphic than the simple rectangle used in the last example. The necessary code is shown in Code Listing 19-2; you can see the output in Figure 19-2.

Code Listing 19-2.

<HTML>
<HEAD>
<TITLE>Code Listing 19-2</TITLE>
</HEAD>
<BODY>
<INPUT TYPE=button VALUE="Bigger" onclick="Idea.Scale(1.2,1.2,0)">
<INPUT TYPE=button VALUE="Smaller" onclick="Idea.Scale(.8,.8,0)">
<BR>
<OBJECT ID="Idea" STYLE="width: 400; height: 400"
  CLASSID="CLSID:369303C2-D7AC-11D0-89D5-00A0C90833E6">
  <PARAM NAME="Line0001" VALUE="SetLineColor(0,0,0)">
  <PARAM NAME="Line0002" VALUE="SetFillColor(255,255,0)">
  <PARAM NAME="Line0003" VALUE="SetLineStyle(6,1)">
  <PARAM NAME="Line0004" VALUE="Polygon(20,-6,-67,-6,-71,-7,-74,-8,-76,
    -10,-79,-10,-82,-9,-84,-6,-86,-4,-87,-2,-86,-1,-86,1,-84,2,-82,2,-79,
    0,-77,-2,-73,-2,-71,-2,-69,-3,-67,-4,-65)">
  <PARAM NAME="Line0005" VALUE="SetLineColor(0,0,0)">
  <PARAM NAME="Line0006" VALUE="SetFillColor(0,0,0)">
  <PARAM NAME="Line0007" VALUE="SetLineStyle(0,1)">
  <PARAM NAME="Line0008" VALUE="Polygon(5,-14,-84,-22,-85,-23,-87,-22,
    -88,-21,-88)">
  <PARAM NAME="Line0009" VALUE="Polygon(5,-10,-92,-14,-96,-14,-98,-12,
    -99,-11,-97)">
  <PARAM NAME="Line0010" VALUE="Polygon(5,-1,-92,-2,-98,0,-100,2,-100,
    1,-98)">
  <PARAM NAME="Line0011" VALUE="Polygon(5,5,-89,11,-94,13,-93,13,-92,
    12,-91)">
  <PARAM NAME="Line0012" VALUE="Polygon(21,1,-48,-3,-54,-7,-58,-12,-58,
    -17,-55,-20,-52,-21,-47,-20,-40,-17,-33,-11,-28,-6,-26,-2,-25,2,-26,
    4,-28,5,-33,5,-39,3,-44,12,-48,12,-50,12,-51,3,-46)">
  <PARAM NAME="Line0013" VALUE="Polygon(38,11,-27,6,-23,4,-22,3,-19,5,
    -16,6,-15,11,-17,19,-23,25,-30,32,-38,32,-41,32,-50,30,-64,32,-72,
    32,-75,31,-77,28,-78,26,-80,28,-87,27,-89,25,-88,24,-79,24,-76,23,
    -75,20,-76,17,-76,17,-74,19,-73,22,-73,24,-71,26,-69,27,-64,28,-55,
    28,-47,28,-40,26,-38,20,-33,14,-30)">
  <PARAM NAME="Line0014" VALUE="Polygon(35,-6,-20,-9,-21,-15,-21,-20,-17,
    -28,-8,-32,-1,-32,1,-30,6,-26,8,-20,10,-16,12,-14,14,-15,16,-18,20,
    -22,20,-25,19,-27,20,-26,22,-23,23,-18,23,-14,22,-11,20,-10,17,-9,14,
    -11,11,-16,9,-22,8,-26,5,-28,2,-27,-2,-23,-8,-19,-11,-12,-14,-6,-15,
    -6,-18)">
  <PARAM NAME="Line0015" VALUE="Polygon(20,11,-6,8,-16,5,-21,-1,-23,-7,
    -22,-10,-17,-9,-10,-8,0,-8,10,-10,18,-11,22,-10,26,-7,28,-3,30,0,31,
    5,31,10,27,14,18,14,11,11,2)">
  <PARAM NAME="Line0016" VALUE="Polygon(28,0,22,-5,21,-8,22,-9,26,-8,49,
    -8,54,-10,64,-10,75,-9,81,-10,84,-16,89,-18,95,-18,97,-13,100,-12,99,
    -12,95,-10,90,-8,87,-6,86,-4,83,-3,82,-5,80,-6,79,-7,74,-6,63,-3,52,
    0,42,1,31)">
  <PARAM NAME="Line0017" VALUE="Polygon(31,12,31,12,24,8,21,3,21,2,24,3,
    30,5,40,8,47,10,56,11,64,11,71,10,76,8,77,8,79,10,81,13,82,17,82,26,
    84,28,87,32,86,33,81,32,80,25,79,17,79,14,79,13,76,14,72,14,64,13,55,
    12,44,12,34)">
</OBJECT>
</BODY>
</HTML>

Click to view at full size.

Figure 19-2. This entire page, including the graphics code, is only 2.67 KB.

Despite the length of Code Listing 19-2, the file size of the entire page, including the structured graphic, is only 2.67 KB. The image shown in Figure 19-2 is also completely scalable. By clicking the buttons in the upper left corner of the page, you can change the size of the image—and you can do it in real time, after the page has loaded. There is no need to load another image or even to refresh the page. This is accomplished by giving the Structured Graphics control's Scale method the factors by which we want to scale the graphic in the x, y, and z axes. In Code Listing 19-2, we scaled the image using the same value for the x and y coordinates to resize the image while maintaining its aspect ratio. You can experiment by using different scale values for the x, y, and z coordinates, which creates the effect of stretching the image. In addition to scale, structured graphics support many other methods, including Clear, Rotate, Translate (moves the graphic), SetIdentity (resets any changes), and Transform4x4 (scales, rotates, and translates all at once).

Code Listing 19-3 uses the structured graphic from Code Listing 19-2, but it adds buttons that allow rotation, stopping of rotation, and resetting to the initial position, as shown in Figure 19-3.

Code Listing 19-3.

<HTML>
<HEAD>
<TITLE>Code Listing 19-3</TITLE>
<SCRIPT LANGUAGE="JavaScript">
var Xint,Yint,Zint
function SpinIt(degX,degY,degZ){ Idea.Rotate(degX,degY,degZ) }
</SCRIPT>
</HEAD>
<BODY>
<INPUT TYPE=button VALUE="RotateX"
  onclick="clearInterval(Xint);Xint=setInterval(`SpinIt(20,0,0)',0100)">
<INPUT TYPE=button VALUE="RotateY"
  onclick="clearInterval(Yint);Yint=setInterval(`SpinIt(0,20,0)',0100)">
<INPUT TYPE=button VALUE="RotateZ"
  onclick="clearInterval(Zint);Zint=setInterval(`SpinIt(0,0,20)',0100)">
<BR>
<INPUT TYPE=button VALUE=" Stop  X " onclick="clearInterval(Xint)">
<INPUT TYPE=button VALUE=" Stop  Y " onclick="clearInterval(Yint)">
<INPUT TYPE=button VALUE=" Stop  Z " onclick="clearInterval(Zint)">
<INPUT TYPE=button VALUE="Initial Position" onclick="Idea.SetIdentity()">
<BR>
<OBJECT ID="Idea" STYLE="width: 250; height: 250"
  CLASSID="CLSID:369303C2-D7AC-11D0-89D5-00A0C90833E6">
  <PARAM NAME="Line0001" VALUE="SetLineColor(0,0,0)">
  <PARAM NAME="Line0002" VALUE="SetFillColor(255,255,0)">
  <PARAM NAME="Line0003" VALUE="SetLineStyle(6,1)">
  <PARAM NAME="Line0004" VALUE="Polygon(20,-6,-67,-6,-71,-7,-74,-8,-76,
    -10,-79,-10,-82,-9,-84,-6,-86,-4,-87,-2,-86,-1,-86,1,-84,2,-82,2,-79,
    0,-77,-2,-73,-2,-71,-2,-69,-3,-67,-4,-65)">
  <PARAM NAME="Line0005" VALUE="SetLineColor(0,0,0)">
  <PARAM NAME="Line0006" VALUE="SetFillColor(0,0,0)">
  <PARAM NAME="Line0007" VALUE="SetLineStyle(0,1)">
  <PARAM NAME="Line0008" VALUE="Polygon(5,-14,-84,-22,-85,-23,-87,-22,
    -88,-21,-88)">
  <PARAM NAME="Line0009" VALUE="Polygon(5,-10,-92,-14,-96,-14,-98,-12,
    -99,-11,-97)">
  <PARAM NAME="Line0010" VALUE="Polygon(5,-1,-92,-2,-98,0,-100,2,-100,
    1,-98)">
  <PARAM NAME="Line0011" VALUE="Polygon(5,5,-89,11,-94,13,-93,13,-92,
    12,-91)">
  <PARAM NAME="Line0012" VALUE="Polygon(21,1,-48,-3,-54,-7,-58,-12,-58,
    -17,-55,-20,-52,-21,-47,-20,-40,-17,-33,-11,-28,-6,-26,-2,-25,2,-26,
    4,-28,5,-33,5,-39,3,-44,12,-48,12,-50,12,-51,3,-46)">
  <PARAM NAME="Line0013" VALUE="Polygon(38,11,-27,6,-23,4,-22,3,-19,5,
    -16,6,-15,11,-17,19,-23,25,-30,32,-38,32,-41,32,-50,30,-64,32,-72,
    32,-75,31,-77,28,-78,26,-80,28,-87,27,-89,25,-88,24,-79,24,-76,23,
    -75,20,-76,17,-76,17,-74,19,-73,22,-73,24,-71,26,-69,27,-64,28,-55,
    28,-47,28,-40,26,-38,20,-33,14,-30)">
  <PARAM NAME="Line0014" VALUE="Polygon(35,-6,-20,-9,-21,-15,-21,-20,-17,
    -28,-8,-32,-1,-32,1,-30,6,-26,8,-20,10,-16,12,-14,14,-15,16,-18,20,
    -22,20,-25,19,-27,20,-26,22,-23,23,-18,23,-14,22,-11,20,-10,17,-9,14,
    -11,11,-16,9,-22,8,-26,5,-28,2,-27,-2,-23,-8,-19,-11,-12,-14,-6,-15,
    -6,-18)">
  <PARAM NAME="Line0015" VALUE="Polygon(20,11,-6,8,-16,5,-21,-1,-23,-7,
    -22,-10,-17,-9,-10,-8,0,-8,10,-10,18,-11,22,-10,26,-7,28,-3,30,0,31,
    5,31,10,27,14,18,14,11,11,2)">
  <PARAM NAME="Line0016" VALUE="Polygon(28,0,22,-5,21,-8,22,-9,26,-8,49,
    -8,54,-10,64,-10,75,-9,81,-10,84,-16,89,-18,95,-18,97,-13,100,-12,99,
    -12,95,-10,90,-8,87,-6,86,-4,83,-3,82,-5,80,-6,79,-7,74,-6,63,-3,52,
    0,42,1,31)">
  <PARAM NAME="Line0017" VALUE="Polygon(31,12,31,12,24,8,21,3,21,2,24,3,
    30,5,40,8,47,10,56,11,64,11,71,10,76,8,77,8,79,10,81,13,82,17,82,26,
    84,28,87,32,86,33,81,32,80,25,79,17,79,14,79,13,76,14,72,14,64,13,55,
    12,44,12,34)">
</OBJECT>
</BODY>
</HTML>

Click to view at full size.

Figure 19-3. The graphic can be rotated around any axis.

The code listing above uses the Rotate and SetIdentity methods of the Structured Graphics control. The Rotate method simply takes the graphic and rotates it a specified number of degrees around the x, y, and z axes. The RotateX, RotateY, and RotateZ buttons each contain an onclick event handler that looks something like the following:

onclick="clearInterval(Xint);Xint=setInterval(`SpinIt(20,0,0)',0100)"

This event handler takes advantage of the setInterval and clearInterval methods. The setInterval method is a method of the window object in both Internet Explorer and Netscape Navigator that allows for an action to be repeated whenever a particular period of time has elapsed. In this case, we specify that the SpinIt function should be called every 100 milliseconds. The SpinIt function rotates the graphic as specified above. Because setInterval repeats the rotate operation, the graphic appears to spin. The Xint variable is used to keep track of the particular timer object used by this setInterval method; it is used by clearInterval to remove any previous spinning occurring around that axis. The Initial Position button uses the SetIdentity method to reset the structured graphic to its initial orientation.

The Structured Graphics control supports a number of useful events, including onclick, ondblclick, onmousedown, onmousemove, onmouseout, onmouseover, and onmouseup.

Using Script Blocks to Capture Events

The best way of capturing an event on a DirectAnimation control is usually with a dedicated script block. For example, you could capture an onmouseout event on the above mentioned Idea structured graphic as follows:

<SCRIPT LANGUAGE="JavaScript" FOR="Idea" EVENT="onmouseout">
[Event handling script here]
</SCRIPT>

This section has supplied only the basics on how to get started with the Structured Graphics control. You can use this control in many other ways and with many additional methods and properties. For more information about structured graphics, check out the Structured Graphics control reference by going to microsoft.com/directx/dxm and then choosing DirectAnimation followed by Multimedia Controls.


The Sequencer Control

The Sequencer control provides a way to command the timing and sequencing of actions on a Web page. The level of control possible with the sequencer is much greater than that provided by the setInterval and setTimeout methods. Like the Structured Graphics control, the sequencer control is added to a page via an <OBJECT> tag. Its CLASSID is as follows:

CLASSID="CLSID:B0A6BAE2-AAF0-11D0-A152-00A0C908DB96"

Code Listing 19-4 demonstrates the Sequencer control by counting down from 3 and displaying the text Ta Da!

Code Listing 19-4.

<HTML>
<HEAD>
<TITLE>Code Listing 19-4</TITLE>
<OBJECT ID="Seq1" CLASSID="CLSID:B0A6BAE2-AAF0-11D0-A152-00A0C908DB96">
</OBJECT>

<SCRIPT LANGUAGE="JavaScript">
Seq1.Item("ActionSet1").At(0.000,"showText(`3')",1,0.050,1);
Seq1.Item("ActionSet1").At(1.000,"showText(`2')",1,0.050,1);
Seq1.Item("ActionSet1").At(2.000,"showText(`1')",1,0.050,1);
Seq1.Item("ActionSet1").At(3.000,"showText(`Ta Da!')",1,0.050,1);

function showText(obj){ Span1.innerHTML=obj }

</SCRIPT>
</HEAD>
<BODY onload="Seq1.Item(`ActionSet1').Play()">
<CENTER>
<SPAN ID="Span1" STYLE="font:48pt bold arial;color:red"></SPAN>
</CENTER>
</BODY>
</HTML>

The Sequencer control works by executing an action set, a script used to control the actions of other objects on the page. An action set is built using the control's At method to identify certain actions that should occur at a specific time. Here is the syntax for the At method:

ObjectID.Item("ActionSetn").At(time,"script",[loop,interval,
  tiebreak,drop threshold])

You must provide values for the time and script arguments in the At method as denoted by the square brackets; the other four arguments are optional. (Do not code the square brackets even if you do include any of the optional arguments.) You can use these six arguments to do the following:

  • Use the time argument to specify the time that the particular action should start, relative to when the overall action set is started. The format for this argument is ss.mss (seconds.milliseconds).

  • Use the script argument to identify the procedure to be executed. This will typically point to a function. You can execute script directly in the At method by using eval or window.execScript instead of specifying a function. For example, in Code Listing 19-4, instead of using the line that calls showText(`Ta Da!'), we could have used:

    Seq1.Item("ActionSet1").At(3.000,"eval(\"Span1.innerHTML=`Ta Da!'\")",
1,0.050,1);

  • Use the loop argument to specify the loop count for the action. A value of 0 prevents or halts execution, a positive number loops the action the specified number of times, and a value of -1 creates an infinite loop. Any other negative number is treated as 0 and prevents or halts execution.

  • Use the interval argument to specify the delay between iterations of the action. The default value is 33 milliseconds (00.033), or 30 frames per second. The format for this argument is ss.mss (seconds.milliseconds).

  • Use the tiebreak argument to specify a priority for the action. If two actions occur at the same time, the action with the lower positive tiebreak number is performed first. A value of -1 (the default) assigns the lowest priority and specifies that the action will be performed last.

  • Use the drop threshold argument to specify the time at which the action will be dropped if it has not been performed. The default value, -1, specifies that the action will never be dropped. The format for this argument is ss.mss (seconds.milliseconds).

Code Listing 19-4 first creates an action set. Once the body of the document has loaded, the control's Play method is called and the action set is started. The showText function is called once every second and changes the contents of the SPAN element so that a countdown occurs. You can use an action set to call a function that contains another action set, putting together complex sequences of actions.

The Sequencer control also supports the Stop, Pause, and Seek methods. Stop resets the timer and stops playing the action set. Pause stops playing the action set but keeps the current position within the list of actions. Seek lets you fast-forward or rewind to a particular point in the list of actions. You can use the PlayState property to tell whether the action set is currently stopped, playing, or paused, and the Time property will tell you how much time has elapsed. The onplay, onpause, onstop, and onseek events are fired as appropriate, and the oninit event is fired when the sequencer completes loading into memory.

NOTE
The syntax for using the Sequencer control is somewhat different if you are coding with VBScript. In JScript, when referring to a particular action set the word Item is used as follows: Seq1.Item(`ActionSet1'). For example, the Play function is called as follows: Seq1.Item(`ActionSet1').Play(). In VBScript, Item is not used. Thus, the equivalent would be Seq1(`ActionSet1').Play().


The Path Control

The Path control provides a powerful, flexible mechanism for controlling the movement of objects over time. This control lets you define a path of almost any shape, target an object to move along the path, set the direction and the duration of movement, and even set markers on the path that can be used to call other events.

Again, an <OBJECT> tag must be added to the page to use the Path control. Its CLASSID is as follows:

CLASSID="CLSID:D7A7D7C3-D47F-11D0-89D3-00A0C90833E6"

<PARAM> tags and script can be used to control many aspects of the Path control's behavior, including the direction of movement and whether the path is used automatically or requires script to start. Here is a partial list of the properties you can use with the Path control.

Property | Description
AutoStart | Specifies whether the path should start playing automatically when it loads (-1 or true) or not (0 or false).
Bounce | Specifies the behavior of the path when it reaches its end. If set to 1 or true, the object on the path will reverse direction and continue in the opposite direction. If set to 0 or false, the object on the path simply stops.
Direction | Specifies whether the path is followed in a forward direction (0) or in reverse (1).
Duration | Specifies the how long the path should take to get from beginning to end in ss.mss (seconds.milliseconds).
PlayState | Returns the playback state of the path. PlayState returns one of three values: 0 if the path is stopped, 1 if the path is playing, and 2 if the path is paused. This property is read-only.
Repeat | Specifies the number of times the path should loop its playback. A value of 0 disables the Repeat property; a value of -1 sets up an infinite loop. The default value is 1.
Target | Specifies the target object (using the value of the object's ID attribute) for the path.
Time | Returns how long the path has been running.
TimerInterval | Specifies how frequently the path is updated.

Code Listing 19-5 demonstrates a simple use of the Path control to manipulate some text around an oval path.

Code Listing 19-5.

<HTML>
<HEAD>
<TITLE>Code Listing 19-5</TITLE>
<OBJECT ID="pthOval"
  CLASSID="CLSID:D7A7D7C3-D47F-11D0-89D3-00A0C90833E6">
  <PARAM NAME="AutoStart" VALUE="true">
  <PARAM NAME="Repeat" VALUE="2">
  <PARAM NAME="Bounce" VALUE="true">
  <PARAM NAME="Duration" VALUE="7">
  <PARAM NAME="Shape" VALUE="Oval(100,75,300,200)">
  <PARAM NAME="Target" VALUE="Text1">
</OBJECT>
</HEAD>
<BODY>
<SPAN ID="Text1" STYLE="position:absolute">An Oval Path</SPAN>
</BODY>
</HTML>

When the page created in Code Listing 19-5 is loaded, the path automatically starts. The path playback is set to take seven seconds to complete. This example uses the Path control's Oval method to define the shape of the path. The Path control supports a number of useful methods, including those listed in the table below.

Method | Description
Oval | Creates an oval as the path, following the same format as the Structured Graphic Oval method.
Polygon | Creates a multisided closed shape for the path.
PolyLine | Creates a path from a set of line segments.
Rect | Creates a rectangle as the path, following the same format as the Structured Graphic Rect method.
Spline | Creates the path from a curve derived from a polynomial function and a set of defining points.
Play | Starts the object moving on the path from the current elapsed time.
Stop | Stops movement and returns path to the beginning.
Pause | Stops movement and keeps the current elapsed time.
Seek | Sets the position to a specified point.
AddTimeMarker Sets a marker that causes an onmarker event to be fired when the path reaches the marker position. The HTML code

<PARAM NAME="AddTimeMarker" VALUE="3,MarkerTest,true">

would cause a marker named MarkerTest to be set three seconds into play. The true value means that marker-related events will be fired. This is the equivalent of the JScript PthOval.AddTimeMarker(3,"MarkerTest,true").
KeyFrame Sets specific x,y points along the path and a designated time to reach each point. It can be set through script as follows:

KeyFrameArray=new Array(x1,y1, x2,y2,...xN,yN)
TimeArray=new Array(Time2, Time3,...TimeN)
PthCtrl.KeyFrame(N,KeyFrameArray,TimeArray)

The Path control also supports a number of useful events. The onplay, onpause, onstop, and onseek events are fired as the state of the control's playback changes. The onmarker and onplaymarker events are fired when the path reaches a point in the path specified with the AddTimeMarker method. The difference between the two is that onplaymarker is fired only if the marker is passed while the control is playing, while onmarker is fired even if the seek method is used to move to that point.


The Sprite Control

If you are familiar with traditional animation techniques, you know that animations are composed of many separate images shown in rapid succession. Each image differs only slightly from the previous one. When the images are played back in rapid succession, the viewer has the impression that the image on the screen is moving.

The DirectAnimation Sprite control allows the Web developer to create animations out of a series of stills and achieve a high level of control over the playback and behavior of these animations. The stills are taken from a single graphics file that contains each of the individual pictures laid out in rows. Sprites give you far more control than is available with a traditional animated GIF. For example, you can seek a specified frame in the animation or change on the fly the time each frame should be displayed.

Like the other DirectAnimation controls, an <OBJECT> tag must be added to the page to use the Sprite control. Its CLASSID is as follows:

CLASSID="CLSID:FD179533-D86E-11D0-89D6-00A0C90833E6"

The Sprite control supports many properties that control everything from the location of the source graphic to a color that should be displayed as transparent. Here are descriptions of some of the more commonly used properties.

Property | Description
AutoStart | Specifies whether the animation automatically begins playback when the page is loaded.
ColorKey | Sets the transparency color in the source image.
UseColorKey | Specifies whether the sprite's transparency information should be used.
Frame | Returns the current frame being played.
InitialFrame | Sets the number of the frame that should be displayed when the control first becomes visible.
FinalFrame | Sets the frame that should be displayed when the animation is stopped.
FrameMap | Sets the order in which the frames are to be played back, along with the amount of time each frame is to be displayed. The format is a list as follows: frame1, time1; frame2, time2, for example 1,.100;2,.100;3,.100.
NumFrames | Sets or returns the number of frames (stills) in the source.
NumFramesDown | Specifies or returns the height of the source image in number of frames.
NumFramesAcross | Specifies or returns the width of the source image in number of frames.
MouseEventsEnabled | Sets whether mouse events on the sprite will be processed.
PlayRate | Specifies the playback rate for the sprite. This property can be used to slow or increase the playback rate or even to make the sprite play backward.
PlayState | Returns one of three playback states for the sprite: play, paused, or stopped.
Repeat | Sets or returns the number of times the sprite should loop.
SourceURL | Specifies the URL that points to the source image.
Time | Returns the total elapsed play time for the sprite.
TimerInterval | Specifies the amount of time between frame updates, expressed in milliseconds.

Code Listing 19-6 demonstrates the Sprite control using a GIF containing images of Earth in different rotational positions to build a frame-based animation that will make it appear as if the Earth is spinning. The sprite in Code Listing 19-6 uses the file earth.gif, which contains 21 images of the Earth, as its source. Figure 19-4 shows a part of earth.gif.

Figure 19-4. Part of the file earth.gif. The file extends downward, containing many more pictures of the Earth.

Each one of the pictures of the Earth is used as a frame in the sprite. When all the frames are played in succession, the globe appears to spin. Notice that we also set the Repeat value to -1, which means that if the animation is playing, it should repeat, or loop, an infinite number of times. Figure 19-5 displays the results.

Code Listing 19-6.

<HTML>
<HEAD>
<TITLE>Code Listing 19-6</TITLE>
</HEAD>
<BODY BGCOLOR="black">
<OBJECT ID="globe" STYLE="width:200;height:150"
  CLASSID="clsid:FD179533-D86E-11D0-89D6-00A0C90833E6">
  <PARAM NAME="NumFrames" VALUE="21">
  <PARAM NAME="NumFramesAcross" VALUE="1">
  <PARAM NAME="NumFramesDown" VALUE="21">
  <PARAM NAME="ColorKey" VALUE="255,0,255">
  <PARAM NAME="UseColorKey" VALUE="-1">
  <PARAM NAME="SourceURL" VALUE="earth.gif">
  <PARAM NAME="Repeat" VALUE="-1">
  <PARAM NAME="InitialFrame" VALUE="1">
</OBJECT><P>
<INPUT TYPE="button" VALUE="Play" onclick="globe.Play()">
<INPUT TYPE="button" VALUE="Pause" onclick="globe.Pause()">
<INPUT TYPE="button" VALUE="Stop" onclick="globe.Stop()">
<INPUT TYPE="button" VALUE="Frame" onclick="alert(globe.Frame)">
<INPUT TYPE="button" VALUE="Time" onclick="alert(globe.Time)">
</BODY>
</HTML>

Click to view at full size.

Figure 19-5. The sprite of the Earth can be manipulated with the on screen buttons.

The Play, Pause, and Stop buttons call the corresponding methods of the Sprite control. The Frame and Time buttons will display an alert showing the current frame number and the amount of time that the control has been playing.

Sprites can be used for more than just simple animation. Code Listing 19-7 uses specific frames of the sprite to allow the user to display various regions of the earth by clicking a button for the desired region. Figure 19-6 shows how Internet Explorer displays this page.

Code Listing 19-7.

<HTML>
<HEAD>
<TITLE>Code Listing 19-7</TITLE>
</HEAD>
<BODY BGCOLOR="black">
<OBJECT ID="globe" STYLE="width:200;height:150"
  CLASSID="clsid:FD179533-D86E-11D0-89D6-00A0C90833E6">
  <PARAM NAME="NumFrames" VALUE="21">
  <PARAM NAME="NumFramesAcross" VALUE="1">
  <PARAM NAME="NumFramesDown" VALUE="21">
  <PARAM NAME="ColorKey" VALUE="255,0,255">
  <PARAM NAME="UseColorKey" VALUE="-1">
  <PARAM NAME="SourceURL" VALUE="earth.gif">
  <PARAM NAME="InitialFrame" VALUE="1">
</OBJECT><P>
<INPUT TYPE="button" VALUE="South America" onclick="globe.FrameSeek(21)">
<INPUT TYPE="button" VALUE="Asia" onclick="globe.FrameSeek(12)">
<INPUT TYPE="button" VALUE="Africa" onclick="globe.FrameSeek(16)">
<INPUT TYPE="button" VALUE="North America" onclick="globe.FrameSeek(2)">
</BODY>
</HTML>

Click to view at full size.

Figure 19-6. Using the Sprite control to enable users to manipulate an image.

When a button is clicked, the FrameSeek method of the Sprite control is called and passed a number as the argument. This number is the frame in the sprite that corresponds to the location to be displayed. This causes the sprite to jump to the frame specified, which makes the specified region appear on the globe.

In addition to FrameSeek, the Sprite control supports the following methods, which behave as they do in other DirectAnimation controls: Play, Pause, Seek, Stop, and AddTime
Marker. Expected events are supported, including onclick, ondblclick, onframeseek, onmarker, onmousedown, onmousemove, onmouseout, onmouseover, onmouseup, onpause, onplay, onplay
marker, onseek, and onstop. The onmedialoaded event is fired when the control and the graphic containing the source images are fully loaded. As mentioned in the note earlier in the chapter, it is best to capture events using a dedicated script block rather than an inline event handler.

The multimedia controls discussed in this chapter can provide lightweight, powerful ways to enhance a Web page and present exciting media content to the user. The Structured Graphics control lets you add small, scalable vector-based images to your Web page. The Sequencer control gives you precise control over the timing of actions on the page. The Path control provides a way to add sophisticated movement to screen objects. And the Sprite control adds the capability of including frame-based animations and images.

The next part of this book will take a look at some advanced Web development techniques, covering everything from working with data using data binding and XML to using DHTML behaviors and creating cross browser scripts.


Chapter 20 -- Data Binding

 Chapter 20

Data Binding

Included in Microsoft Internet Explorer is a useful and timesaving technology called data binding. Data binding offers advantages to both the Web developer and the user by making Web pages easier to create and update, faster to load, and less dependent on remote servers. It does all this by allowing a Web page's data to be kept locally and separate from the HTML code that formats it. Through what are called data source objects (DSOs), the Web page becomes a kind of template that can be filled with the external data, which can be displayed and manipulated. In this chapter, we'll discuss how data binding and DSOs work, and then we'll explore some examples that use a specific DSO called the Tabular Data Control (TDC). These examples demonstrate how to access the powerful features of data binding with simple scripts. Although Netscape Navigator does not support binding data directly to HTML elements, it does support a DSO called the Java Database Connectivity (JDBC) applet, which will also be discussed in this chapter. Finally we'll take a brief look at more advanced aspects of data binding.


Advantages of Data Binding

Data binding offers some interesting advantages to both the Web developer and the end user. One of these advantages is reduced reliance on remote servers for data updates and manipulation. To understand this, let's look at an example of a Web site that lists herbs and their uses to examine how data was processed and accessed by the Web user before the advent of data binding.

Since Web sites built around databases are becoming common, let's assume that all of your herb information is stored in a database. If a user wants to see all the herbs on your site sorted by their common names, the user makes the request, usually through an HTML form. The server then retrieves the requested information from the database, processes it using some sort of server-side technology such as Microsoft Active Server Pages (ASP), Common Gateway Interface (CGI), or Internet Server API (ISAPI) scripts, creates a Web page out of the information, and sends the newly created file back to the user's browser.

Generally, any additional user requests require more trips back to the server. If, for example, the user wants to see the same herbs sorted by their botanical names, he or she would have to submit another request and the whole unwieldy process would start over again. This time-consuming and inefficient procedure not only burdens the server with hundreds or thousands of requests at one time (depending on how popular the Web sites it serves are), it also adds to the already heavy Internet traffic.

Data binding significantly alleviates this congestion by sending the necessary underlying data directly to the user the first time a request is made and manipulating it in response to subsequent requests by using a DSO on the Web page. Another advantage of this process is that the Web developer can give the user as much, or as little, control over the downloaded data as desired. For example, the developer can allow the user to sort, filter, or otherwise change the view of the original data without returning to the server (unless a completely different set of data is needed). You might expect that this initial downloading of large amounts of data would take a great deal of time. However, because Internet Explorer loads the data asynchronously—that is, it starts to display and render the page as soon as there is enough data to do so—the user can interact with the Web page before all the data is available.


Data Source Objects

Data source objects implement a standardized model for delivering data to a Web-based document. The DSO allows a developer to decide the following:

  • How the data will be transported (using the HTTP protocol, for example)

  • How the data can be manipulated (sorting and filtering, for example)

  • Whether the data can be updated and, if so, what mechanism will be used for updating

  • How the data is stored (straight text or SQL, for example)

  • An object model for accessing the data with scripts

Internet Explorer ships several DSOs; however, sophisticated programmers might want to develop their own. DSOs can be written in languages such as Java or C++. Once written, the DSO works directly with Internet Explorer through a common interface. The data from a DSO can be manipulated through script on the Web page, or it can be automatically bound to particular HTML elements through data binding extensions supported by Internet Explorer.

Fortunately, you don't have to write your own DSO to take advantage of the data binding capabilities of Internet Explorer. The DSOs included with Internet Explorer are the Remote Data Service (RDS), the JDBC Java applet, the Tabular Data Control (TDC), and the extensible markup language DSO (XML DSO, discussed in a later chapter). Each DSO has its own benefits and drawbacks.

The Remote Data Service lets users work directly from a Web page to access, manipulate, and update data on any OLE DB provider (a term we'll explain later), including ODBC-compliant databases. (ODBC stands for open database connectivity, and as its name suggests, is an interface that allows access to databases.) Easy access to data has important implications for people working in disparate locations who share a central database such as one on a corporate LAN or WAN.

The JDBC applet is JavaBeans compatible and is supported in modern versions of Netscape Navigator as well as Internet Explorer 4 and 5. Netscape Navigator does not support automatic data binding to HTML elements in the same way as Internet Explorer, but the data can still be made accessible to scripts.

The Tabular Data Control, which uses a simple text file as the data source, is the easiest to implement and use on the client. Its major drawback is that it does not directly support the updating of data on the server. We will be using the TDC for most of the examples in this chapter.

DSOs can be written to perform various database functions. The Tabular Data Control, for example, can display, sort, and filter data by using script and Dynamic HTML. This functionality is possible because the DSO allows the data to be separated from the HTML code. As we described earlier, the DSO/data binding model treats the Web page as a template, which is filled with the data as specified by the DSO. The best online general programmer's reference for Microsoft data access technologies can be found at microsoft.com/data.

How Data Gets from the DSO to the Page

For a DSO to work, it must be present on the Web page (usually as an ActiveX control or Java applet). Once the DSO is on a page, two other types of components—data consumers and binding agents—are used to bring the data itself onto the page.

The Web page elements that render the data supplied by the DSO are called data consumers. These elements can be standard HTML tags such as SPAN, DIV, or TABLE or external objects such as ActiveX controls or Java applets. The data consumer used depends on the type of data supplied, which can be either single-value or tabular. For example, the DIV element could be used to display a single value from the current record supplied by the data source. The TABLE element, in contrast, could display an entire set of records from the data source.

Internet Explorer supports several HTML attributes used expressly for data binding by elements that are data consumers:

  • The DATASRC attribute identifies the DSO object by the object's ID.

  • The DATAFLD attribute indicates the column (the data field) exposed by the DSO.

  • The DATAFORMATAS attribute specifies how the data should be formatted—for example, in HTML orplain text.

  • The DATAPAGESIZE attribute indicates how many records are displayed at one time (for tables only).

Binding agents are also built-in components of Internet Explorer. They work completely in the background to identify and maintain the data supplied by the DSO. When a page is loaded, a binding agent identifies all the DSOs and data consumers on the page. It then maintains the synchronization of data between the DSO and data consumers and directs the data traffic both ways, from the DSO to the data consumer and, if the data is changed on the page, from the data consumer to the DSO. Now that you have some background information, let's get to work and do some data binding.


The Tabular Data Control

The tabular data control (TDC) is a built-in ActiveX control. Instead of getting its data from a standard database, this DSO uses a delimited text file as a source of data. Delimited text simply means the data is in a text file in which data items and data rows are separated by common entities. For example, in the text Dill|Anethum graveolens|Culinary and Medicinal, each data item is separated by the pipe character (|). Another common type of delimited text file is known as a comma-separated-values file, or CSV.

Let's look at a more detailed data sample.

Angelica                Angelica archangelica     Culinary

Basil                   Ocimum   basilicum        Culinary and Medicinal

Basil, Cinnamon         Ocimum   basilicum        Culinary and Medicinal

Basil, Holly            Ocimum   basilicum        Culinary and Medicinal

Basil, Spicy Globe      Ocimum   basilicum        Culinary and Medicinal

Each item in the tabular text above is a field, and a horizontal group of fields is called a row. If we convert this database table to a delimited text file using the pipe character as the field delimiter and the newline character as the row delimiter, the result looks like this:

Angelica|Angelica archangelica|Culinary
Basil|Ocimum basilicum|Culinary and Medicinal
Basil, Cinnamon|Ocimum basilicum|Culinary and Medicinal
Basil, Holly|Ocimum basilicum|Culinary and Medicinal
Basil, Spicy Globe|Ocimum basilicum|Culinary and Medicinal

Notice that each horizontal row in the table becomes a line in the text file. Of course, the different characters you choose for delimiters depend on what data you expect in the fields. For example, if you expect a data item to contain multiple lines of text, you might not want to use the newline character as a row delimiter. A text qualifier (covered later in the chapter) is an optional type of delimiter that can help ensure that a whole field is treated as one data item.

Binding Data to a Single-Value Element

Despite the word "tabular" in its name, the tabular data control supports single-value data as well as tabular data. Our first example demonstrates how to use the TDC to bind data to a single-value HTML element. In this example, we will use the above herb data to fill a SPAN element. The data file herbs.txt is the delimited text file with our information about the herbs.

In this file, we use two delimiters: a text qualifier (the exclamation point, !) and a field delimiter (the pipe character, |). The text qualifier specifies the boundaries for each block of text, allowing us to include items in our text that might be used elsewhere as delimiters. (See the sidebar "Understanding Delimiters" for more information.) The field delimiter specifies the boundaries for each field in a record.

Understanding Delimiters
At first glance, it might seem like text qualifiers and field delimiters serve the same purpose, but in fact they are quite different. By using both kinds of delimiters, developers are free to use almost any character they want in text, including characters used as delimiters elsewhere in the data file. For example, imagine a data file in which the pound sign (#) is used as a field delimiter and the exclamation point (!) is used as a text qualifier. If you needed to include the pound sign in one text field, you could enclose it inside a text qualifier and it would be displayed as text rather than interpreted as a field delimiter. Thus, the data #!This is the pound # sign!# would be treated as a single piece of data containing This is the pound # sign.

Our TDC examples will all use the herbs.txt file, which is included on the CD as chap20\herbs.txt. Here are the first 15 lines of herbs.txt. Note the difference between the first row (known as the header row) and the successive lines of text.

common|botan|usage
!Angelica!|!Angelica archangelica!|!Culinary!
!Basil!|!Ocimum basilicum!|!Culinary and Medicinal!
!Basil, Cinnamon!|!Ocimum basilicum!|!Culinary and Medicinal!
!Basil, Holly!|!Ocimum basilicum!|!Culinary and Medicinal!
!Basil, Spicy Globe!|!Ocimum basilicum!|!Culinary and Medicinal!
!Bay!|!Laurus nobilis!|!Culinary!
!Laurel, Sweet!|!Laurus nobilis!|!Culinary!
!Borage!|!Borago officinalis!|!Culinary and Medicinal!
!Burnet!|!Sanguisorba minor!|!Culinary!
!Catnip!|!Nepeta cataria!|!Culinary!
!Catmint!|!Nepeta cataria!|!Culinary!
!Chamomile!|!Chamaemelum nobile!|!Medicinal!
!Chervil!|!Anthriscus cerefolium!|!Culinary!
!Chives!|!Allium schoenoprasum!|!Culinary and Medicinal!

Now that you have seen the herbs.txt file, let's look at the HTML code for our first and most basic example, shown in Code Listing 20-1. Figure 20-1 shows the results of running the code. Note that even though the text Angelica does not appear in the HTML source of the code listing, it is displayed on screen because it is read from the data file.

Code Listing 20-1.

<HTML>
<HEAD>
<TITLE>Code Listing 20-1</TITLE>
<OBJECT ID="herbTDC" CLASSID="CLSID:333C7BC4-460F-11D0-BC04-0080C7055A83">
  <PARAM NAME="TextQualifier" VALUE="!">
  <PARAM NAME="FieldDelim" VALUE="|">
  <PARAM NAME="DataURL" VALUE="herbs.txt">
  <PARAM NAME="UseHeader" VALUE="true">
</OBJECT>
</HEAD>
<BODY>
<B>Common Name-</B><SPAN DATASRC="#herbTDC" DATAFLD="common"></SPAN>
</BODY>
</HTML>

The OBJECT element at the top of the page sets up the TDC as our DSO and specifies a number of parameters, including herbs.txt as the target data file. The first column of the herb data file lists the herbs by their common names. This column is bound to the SPAN element. Notice that the <SPAN> tag in Code Listing 20-1 contains the DATASRC attribute,

Figure 20-1. A single-value HTML element is bound to a data file.

which identifies the data source (the DSO) by its ID. Notice also that the syntax for the data source ID requires that a pound sign (#) precede the object name. The DATAFLD attribute identifies the data field (the column) to which the SPAN element is bound—in this case, the column named common.

The DSO knows the names of the columns in the database because they are defined in the data file. The column names appear in the first line of the herbs.txt file, where they are surrounded by field delimiters only, not by text qualifiers. Because we set the DSO's UseHeader property to true in a <PARAM > tag, the DSO knows to use the first line of the text file for column names. If you have not set up column names and your file contains only data, you can refer to a field by its column number. For example, instead of using DATAFLD=
"common" we could have used DATAFLD="Column1". Remember that for column numbers to function properly, the UseHeader property cannot be set to true.

Of course, our data file contains more than just the common name of the first herb; not only does the record contain the herb's botanical name and some information about its prevalent usage, there are also many different varieties of herbs represented. Code Listing 20-2 demonstrates how to display this information, how to move from one record to another in the database, and how to access the data through script.

Code Listing 20-2.

<HTML>
<HEAD>
<TITLE>Code Listing 20-2</TITLE>
<OBJECT ID="herbTDC" CLASSID="CLSID:333C7BC4-460F-11D0-BC04-0080C7055A83">
  <PARAM NAME="TextQualifier" VALUE="!">
  <PARAM NAME="FieldDelim" VALUE="|">
  <PARAM NAME="DataURL" VALUE="herbs.txt">
  <PARAM NAME="UseHeader" VALUE="true">
</OBJECT>

<SCRIPT LANGUAGE="JavaScript" FOR="window" EVENT="onload">
  herbRS=herbTDC.recordset
  herbRS.MoveFirst()
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript">
function displayInfo(){
  CurPos=("Record "+herbRS.AbsolutePosition+" of "+herbRS.RecordCount)
  CurVal1=("\nField 1=" + herbRS.fields(`common') )
  CurVal2=("\nField 2=" + herbRS.fields(`botan') )
  CurVal3=("\nField 3=" + herbRS.fields(`usage') )
  alert(CurPos+CurVal1+CurVal2+CurVal3)
}
</SCRIPT>
</HEAD>
<BODY>
<INPUT TYPE="button" VALUE="<<" onclick="herbRS.MoveFirst()">
<INPUT TYPE="button" VALUE="<"
  onclick="herbRS.MovePrevious();if(herbRS.BOF)herbRS.MoveFirst()">
<INPUT TYPE="button" VALUE="Display Info" onclick="displayInfo()">
<INPUT TYPE="button" VALUE=">"
  onclick="herbRS.MoveNext();if(herbRS.EOF)herbRS.MoveLast()">
<INPUT TYPE="button" VALUE=">>" onclick="herbRS.MoveLast()">

<P><B>Common Name-</B><SPAN DATASRC="#herbTDC" DATAFLD="common"></SPAN>
<P><B>Botanical Name-</B><SPAN DATASRC="#herbTDC" DATAFLD="botan"></SPAN>
<P><B>Usage-</B><SPAN DATASRC="#herbTDC" DATAFLD="usage"></SPAN>
</BODY>
</HTML>

Click to view at full size.

Figure 20-2. All columns of the record are displayed, and controls that let you move through and examine the data are added.

To display the information about each herb, more SPAN elements were added below the original one and bound to the appropriate columns in the data file. Because each SPAN element is bound to a different data field, the data fields for a record are displayed in their respective SPAN elements each time the TDC moves to a new record.

A script is run when the page is loaded that sets the variable herbRS to reference the recordset child object of the herbTDC object. All DSOs support the recordset object, which can be used to navigate through the data and to insert, delete, and update records.

At the top of the page, four directional buttons, labeled <<, <, >, and >> let the user browse through the herb names in the data file. Depending on which button the user clicks, the MoveFirst, MovePrevious, MoveNext, or MoveLast function of the recordset object is called, and the current display is changed. You've probably noticed the extra code on the < and > buttons in Code Listing 20-2. This code tests the BOF (beginning of file) and EOF (end of file) properties of the recordset object, letting us know where we are in the file and preventing us from moving outside the recordset boundaries.

The Display Info button runs the displayInfo function. This function collects information about the current position in the recordset and then displays it in an alert box. The AbsolutePosition property contains the current position in the recordset. This property can also be set to a particular numeric value to jump to that row in the data. The RecordCount property contains the total number of rows in the database. The fields method of the recordset object returns the value of a particular field of data in the current row of the data.

HTML Elements That Support Single-Value Data Binding

Internet Explorer includes support for binding data to many common HTML elements in addition to SPAN. Table 20-1 lists HTML elements that support data binding, describes what aspect of the element is bound, and indicates whether the element supports the ability to update data in the recordset. All the elements included in this table support single-value data; only the TABLE element (not listed in the table but discussed in the next section) supports tabular data.

Table 20-1 HTML Elements That Support Single-Value Data Binding

HTML Element | DSO Binds To | Supports Updating
A | HREF | No
APPLET | Property value of <PARAM> | Yes
BUTTON | innerText, innerHTML | No
DIV | innerText, innerHTML | No
FRAME | SRC | No
IFRAME | SRC | No
IMG | SRC | No
INPUT TYPE=checkbox | CHECKED | Yes
INPUT TYPE=hidden | VALUE | Yes
INPUT TYPE=label | VALUE | Yes
INPUT TYPE=password | VALUE | Yes
INPUT TYPE=radio | CHECKED | Yes
INPUT TYPE=text | VALUE | Yes
LABEL | innerText, innerHTML | No
MARQUEE | innerText, innerHTML | No
SELECT | text property of currently selected OPTION | Yes
SPAN | innerText, innerHTML | No
TEXTAREA | VALUE | Yes

Binding Data to a TABLE Element

In the previous section, you saw how the ability to display record data in single-value HTML elements gives the developer and the user more options and greater control over the data. But what if you need to display an entire recordset? Two quite labor-intensive approaches would be either to create a separate data-bound element for every field in every row of data or to write some script that would explicitly create a Web page with all the necessary elements. Fortunately, there is a much easier way. Using the HTML <TABLE> tag, you can render all the fields of data in a DSO with very little work.

Code Listing 20-3 shows the extensive amount of code required just to build a table of five herb records without using data binding. Figure 20-3 shows the table produced by this code.

Code Listing 20-3.

<HTML>
<HEAD>
<TITLE>Code Listing 20-3</TITLE>
</HEAD>
<BODY>
<TABLE BORDER="1" CELLSPACING="0">
  <THEAD>
    <TR>
      <TD><B>Common Name</B></TD>
      <TD><B>Botanical Name</B></TD>
      <TD><B>Usage</B></TD>
    </TR>
  </THEAD>
    <TR>
      <TD>Angelica</TD>
      <TD>Angelica archangelica</TD>
      <TD>Culinary</TD>
    </TR>
    <TR>
      <TD>Basil</TD>
      <TD>Ocimum basilicum</TD>
      <TD>Culinary and Medicinal</TD>
    </TR>
    <TR>
      <TD>Basil, Cinnamon</TD>
      <TD>Ocimum basilicum</TD>
      <TD>Culinary and Medicinal</TD>
    </TR>
    <TR>
      <TD>Basil, Holly</TD>
      <TD>Ocimum basilicum</TD>
      <TD>Culinary and Medicinal</TD>
    </TR>
    <TR>
      <TD>Basil, Spicy Globe</TD>
      <TD>Ocimum basilicum</TD>
      <TD>Culinary and Medicinal</TD>
    </TR>
  </TABLE>
</BODY>
</HTML>

Click to view at full size.

Figure 20-3. A table of data constructed without using data binding.

Data binding simplifies the programming process by significantly reducing the amount of code needed to build a table of data. With data binding, all 60 records in the data file can be shown with less code than it took to show just five records in a table built by hand. The code shown in Code Listing 20-4 uses data binding. Figure 20-4 shows the table that results when this code is executed. You'll notice that except for the size, the two displayed tables are basically the same.

Code Listing 20-4.

<HTML>
<HEAD>
<TITLE>Code Listing 20-4</TITLE>
<OBJECT ID="herbTDC" CLASSID="CLSID:333C7BC4-460F-11D0-BC04-0080C7055A83">
  <PARAM NAME="TextQualifier" VALUE="!">
  <PARAM NAME="FieldDelim" VALUE="|">
  <PARAM NAME="DataURL" VALUE="herbs.txt">
  <PARAM NAME="UseHeader" VALUE="true">
</OBJECT>
</HEAD>
<BODY>
<TABLE DATASRC="#herbTDC" BORDER="1" CELLSPACING="0">
  <THEAD>
    <TR>
      <TD><B>Common Name</B></TD>
      <TD><B>Botanical Name</B></TD>
      <TD><B>Usage</B></TD>
    </TR>
  </THEAD>
  <TR>
    <TD><SPAN DATAFLD="common"></SPAN></TD>
    <TD><SPAN DATAFLD="botan"></SPAN></TD>
    <TD><SPAN DATAFLD="usage"></SPAN></TD>
  </TR>
</TABLE>
</BODY>
</HTML>

If you wanted to update the contents of the table constructed by Code Listing 20-3 on the previous page (without data binding), you would need to change each cell of the table in the HTML code. To modify the table constructed by Code Listing 20-4 (with data binding), you would simply need to change the data file. For example, a modified data file could contain herb information written in a language other than English. This would prevent the translators from having to interact with the HTML code.

Click to view at full size.

Figure 20-4 A table of data constructed with data binding.

Manipulating Data

The data can be manipulated in a number of ways once it is on the Web page. For example, data can be sorted, filtered, changed, added, and deleted.

Sorting and Filtering

The TDC is one DSO that supports both sorting and filtering operations. As you can see below, Code Listing 20-5 shows how we enhanced our herb Web page to allow the user to sort the list by common name, botanical name, or usage, and to filter the entire list by particular type of usage. The page now includes a list box for each action (sorting and filtering). When one of the list boxes is changed, the appropriate action is carried out. Figure 20-5 shows the table after it has been sorted by common name and filtered to display only those herbs used for both culinary and medicinal purposes.

Code Listing 20-5.

<HTML>
<HEAD>
<TITLE>Code Listing 20-5</TITLE>
<OBJECT ID="herbTDC" CLASSID="CLSID:333C7BC4-460F-11D0-BC04-0080C7055A83">
  <PARAM NAME="TextQualifier" VALUE="!">
  <PARAM NAME="FieldDelim" VALUE="|">
  <PARAM NAME="DataURL" VALUE="herbs.txt">
  <PARAM NAME="UseHeader" VALUE="true">
</OBJECT>
</HEAD>
<BODY>
<B>Sort by:</B>
<SELECT onchange="herbTDC.Sort=(`+'+this.value); herbTDC.Reset()">
  <OPTION VALUE="">None</OPTION>
  <OPTION VALUE="common">Common Name</OPTION>
  <OPTION VALUE="botan">Botanical Name</OPTION>
  <OPTION VALUE="usage">Usage</OPTION>
</SELECT>
<B>Filter by:</B>
<SELECT onchange="herbTDC.Filter=(`usage=`+this.value); herbTDC.Reset()">
  <OPTION VALUE="">None</OPTION>
  <OPTION VALUE="Culinary">Culinary</OPTION>
  <OPTION VALUE="Medicinal">Medicinal</OPTION>
  <OPTION VALUE="Culinary and Medicinal">Culinary and Medicinal</OPTION>
</SELECT>
<P>
<TABLE DATASRC="#herbTDC">
  <THEAD>
    <TR>
      <TD><B>Common Name</B></TD>
      <TD><B>Botanical Name</B></TD>
      <TD><B>Usage</B></TD>
    </TR>
  </THEAD>
    <TR>
      <TD><SPAN DATAFLD="common"></SPAN></TD>
      <TD><SPAN DATAFLD="botan"></SPAN></TD>
      <TD><SPAN DATAFLD="usage"></SPAN></TD>
    </TR>
</TABLE>
</BODY>
</HTML>

In Code Listing 20-5, the sorting and filtering arguments are kept in the two SELECT elements. When the user selects an option in one of the list boxes, first either the Sort or the Filter property of the TDC is set, and then the Reset method is called to reload the data based on the new settings for the Sort or Filter property.

The Sort property can be set to sort by single or multiple columns and in ascending or descending order. To sort in ascending order by the common field, you can specify herbTDC .Sort="+common" and then use herbTDC.Reset() to apply the sort string. To sort in ascending order by usage and then in descending order by common, you can specify herbTDC .Sort="+usage; -common".

The Filter property allows for the displayed data to be limited to a specific subset of the overall data. An example of a simple filter would be herbTDC.Filter="usage=Culinary". It would display only items with a value in the usage column of Culinary. A more complex filter would be herbTDC.Filter="usage<>Culinary & (common=Oregano | common>Sage)", which would display only items in which the usage field was not equal (<>) to Culinary and (&) the common field either contained Oregano or ( | ) came after Sage in the alphabet. More information about complex filtering can be found on the SBN Workshop Web site and on the CD that accompanies this book. On the CD, see \WORKSHOP\DATABASE\TDC\REFERENCE\FILTER.HTM. To get to the online version, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm, or open the file MSDN_OL.htm on the companion CD, and then choose Filter Property.

Click to view at full size.

Figure 20-5. The same set of records after being sorted and filtered.

Adding, Changing, and Deleting Data

Some DSOs allow the user to modify a recordset by changing a field and by adding or deleting data from the active recordset in memory. The TDC is one such DSO (although it does not allow changes to be made to the source data file). The syntax for the AddNew method is as follows:

dsoID.recordset.AddNew()

Once the AddNew method is used, a new, empty record is added to the end of the recordset. The empty fields can be filled through script or through an HTML element that supports recordset updating. (See Table 20-1 on page 349.) The syntax for changing a field is as follows:

dsoID.recordset.fields(`column name')="new value"

We could have applied these techniques to the previous code listings as follows:

herbRS.AddNew()
herbRS.fields(`common')="Dhaction"
herbRS.fields(`botan')="Dynamicia HTMLicus in Actionious"
herbRS.fields(`usage')="Creating Cool Web Pages"

The Delete method works in a similar fashion, using this syntax:

dsoID.recordset.Delete()

This technique deletes the active record from the recordset. Adding and changing a recordset is demonstrated in Code Listing 20-6.

Although the TDC does not support changing data on the remote source, other DSOs—for instance RDS—do include this feature. Information about RDS and other DSOs can be found on the SBN Workshop Web site and on the CD that accompanies this book. On the CD, see DHTML, HTML, & CSS/Data Binding/Adding a Data Source Object to a Page. To get to the online version, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm, or open the file named MSDN_OL.htm on the companion CD, and then choose Adding a DSO. As stated earlier, the Microsoft Universal Data Access site (microsoft.com/data) also provides useful technical information and further references about DSOs and data access in general.

Data Events

A number of tools are available for controlling and interacting with data bound elements on a page. Data bound elements are HTML elements that have been linked to a DSO that contains data. Using standard Object Model events, content developers can write scripts that will react to changes in data or data bound elements.

Dynamic HTML Data Binding Events

Internet Explorer supports many data binding events, some of which apply to the DSO, others that apply to the data bound elements, and one that applies only to the window object. The following list describes the most common data binding events:

Data Binding Event | Event Object
onbeforeupdate | Data bound element
onafterupdate | Data bound element
onerrorupdate | Data bound element
onbeforeunload | window object
onrowenter | DSO
onrowexit | DSO
ondataavailable | DSO
ondatasetcomplete | DSO
ondatasetchanged | DSO
onreadystatechange | DSO

The script code in Code Listing 20-6 uses both the ondatasetcomplete and ondatasetchanged events. The ondatasetcomplete event is fired when the data is fully loaded. It can be used to ensure that no attempts are made to access content that has not yet loaded. The ondatasetchanged event is fired whenever there is a change in the way the working set of data is sorted or filtered. Note that each of these events is fired both when the page is loaded and every time a new sort operation is performed.

Code Listing 20-6.

<HTML>
<HEAD>
<TITLE>Code Listing 20-6</TITLE>
<OBJECT ID="herbTDC" CLASSID="CLSID:333C7BC4-460F-11D0-BC04-0080C7055A83">
  <PARAM NAME="TextQualifier" VALUE="!">
  <PARAM NAME="FieldDelim" VALUE="|">
  <PARAM NAME="DataURL" VALUE="herbs.txt">
  <PARAM NAME="UseHeader" VALUE="true">
</OBJECT>
<SCRIPT LANGUAGE="JavaScript" FOR="window" EVENT="onload">
  herbRS=herbTDC.recordset;
  herbRS.MoveFirst()
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript" FOR="herbTDC" EVENT="ondatasetcomplete">
  alert("The data is fully loaded.")
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript" FOR="herbTDC" EVENT="ondatasetchanged">
  alert("The working data set has changed.")
</SCRIPT>
</HEAD>
<BODY>
<INPUT TYPE="button" VALUE="Add Record"
  onclick="herbRS.AddNew();
           herbRS.fields(`common')=`Dhaction';
           herbRS.fields(`botan')=`Dynamicia HTMLicus in Actionious';
           herbRS.fields(`usage')=`Creating Cool Web Pages'">
<B>Sort by:</B>
<SELECT onchange="herbTDC.Sort=(`+'+this.value); herbTDC.Reset()">
  <OPTION VALUE="">None</OPTION>
  <OPTION VALUE="common">Common Name</OPTION>
  <OPTION VALUE="botan">Botanical Name</OPTION>
  <OPTION VALUE="usage">Usage</OPTION>
</SELECT>
<TABLE DATASRC="#herbTDC">
  <THEAD STYLE="font-weight: bold">
    <TR><TD>Common Name</TD><TD>Botanical Name</TD><TD>Usage</TD></TR>
  </THEAD>
    <TR>
      <TD><SPAN DATAFLD="common"></SPAN></TD>
      <TD><SPAN DATAFLD="botan"></SPAN></TD>
      <TD><SPAN DATAFLD="usage"></SPAN></TD>
    </TR>
</TABLE>
</BODY>
</HTML>


Additional Ways to Get Data

There are many different potential sources for data. Earlier, we used data that resides in a plain text file. Frequently, data is kept in an online database. Several DSOs such as RDS and JDBC can access these directly. You can also use many server-side technologies to access data. Active Server Pages technology (part of Microsoft Windows NT Server_Internet Information Services) supports directly connecting to databases, such as Microsoft SQL Server. Code Listing 20-7 contains an example of such a page. Note that this page will not work directly from the CD. It must be run on a properly configured server.

Code Listing 20-7.

<%@ LANGUAGE="JScript"%>
<HTML>
<HEAD>
<TITLE>Code Listing 20-7</TITLE>
<%
Conn = Server.CreateObject("ADODB.Connection")
Conn.Open("DSN", "id", "password")
rsFiles=Conn.execute("SELECT FName, LName FROM NameTbl WHERE Reg=1")
rsFiles.MoveFirst()
%>
</HEAD>
<BODY>
<TABLE BORDER="1">
  <THEAD>
  <TR><TD>First Name</TD><TD>Last Name</TD></TR>
  </THEAD>
<%
while (!rsFiles.EOF){
  %>
  <TR><TD><%=rsFiles(0)%></TD><TD><%=rsFiles(1)%></TD></TR>
  <%
  rsFiles.MoveNext()
}
Conn.Close()
%>
</TABLE>
</BODY>
</HTML>

Much of the content in Code Listing 20-7 is beyond the scope of this book; however, here is a quick rundown of what it does: Active Server Pages allows you to mix server-side script into a client-side Web page. The <% and %> characters are one way to signify the beginning and end of a server-side script block. The first line of server-side script notifies the server that the ASP page uses JScript. The next server-side script block creates a connection object and opens a connection to a database, where DSN signifies the Data Source Name of the database (found in the Control Panel for ODBC on the server), id is the desired user, and password is the password used to access the database. The rsFiles recordset is created from a standard SQL query against the database, asking for the FName and LName fields of all the records in the NameTbl table for which the Reg field is set to 1. The recordset is then set to the first record.

The beginning of a table is written to the client-side page, and then the next block of server-side script begins. This loops through all the records in the recordset, writing a line of HTML to the page that consists of a table row with the contents of the first and second fields of the current record, each in their own cell. The syntax <%=variableName%> will write the content of variableName to the HTML page. When the loop finishes, the connection to the database is closed to reduce the load on the server. Finally the table and the rest of the Web page are closed. This ASP page will return a table of first and last names from a database.


Additional Ways to Use Data Binding

Now that you understand how data binding works, we'll conclude by offering a few practical ideas of how you might begin to use this capability.

  • A Web site that is translated into different languages Wherever text needs to be used on the site, you could substitute a data bound element. You could then pull all of the text from an external data source, using a different data source for each language.

  • A front end to a corporate database Users throughout a company could access a database from a page on the company's intranet.

  • An online storefront All product information could be stored and maintained in a database and displayed on a Web site. Customers could view product information by price, availability, or any other appropriate criteria. Customer information could be posted to a customer database using data bound controls on the site.

  • A reference Web site Reference databases could be bound to Web pages using the data binding controls. Users could search the database and modify views of the data after it is downloaded. Many parts of the SBN Workshop function in this way; for example, on the companion CD, see the first table found in \WORKSHOP\AUTHOR\DATABIND\OBJMODEL.HTM.

Data binding is a powerful and flexible way to work with external data from within Web-based documents. Using data binding and a data source object, you can allow users to view data in various ways, sort and filter the data, and add or delete data. By using the data binding features of Internet Explorer, you can create powerful database-driven applications on a Web-based platform.


Chapter 21 -- XML

 Chapter 21

XML

Extensible Markup Language (XML) is designed to complement, not replace, HTML. It, too, is a way to describe structured data. But unlike an HTML file, an XML file does not hold any information about how the data should be displayed; it simply contains the data in a highly organized and descriptive form. One reason XML is used by so many different applications is that it is only a data format. For example, stock information created in the XML format can be displayed by a browser on the Web, imported as a table into a database, and even read by a text editor. This flexibility is possible, in part, because there are no instructions in an XML file that specify the way the data is displayed; the file is simply structured data. This chapter begins with an overview of some of the concepts behind XML and then focuses on how to create XML files and how Microsoft Internet Explorer can be used to integrate XML into a Web page. Netscape Navigator does not provide the same type of XML support found in Internet Explorer.


Background of XML

The ancestor of both HTML and XML is the Standard Generalized Markup Language, SGML for short. This expansive language allows the creation of complex systems (or applications) of data and includes rules on how to describe and display that data. For example, HTML is an application of SGML. XML, on the other hand, is a subset of SGML, designed to provide a simple, Web-optimized way to represent data that is easier to work with than full-blown SGML.

The Case for XML

XML was designed with the Web in mind and brings to the table some benefits not found in SGML. Browsers can use XML in combination with HTML for data display and presentation. Two related specifications have been created to support the delivery of XML over the Web.

The Extensible Linking Language (XLL) specification describes a hyperlinking scheme that not only supports basic HTML hyperlinking but also extended linking, which allows functionality such as letting a single link point to multiple resources. Although SGML would allow a hyperlinking mechanism to be defined, it does not include hyperlinking as part of its original specification.

The Extensible Stylesheet Language (XSL) specification gives support for an XML style sheet mechanism, a feature also not found in straight SGML. Style sheets allow authors to create templates of styles (such as bold, italic, and so on) or combinations of styles, and apply them to elements in an XML document when it is displayed.

Simply put, XML provides 80 percent of the features and functionality of SGML with 20 percent of its complexity. Having a simple, generic way of describing data is very useful. For example, XML can function as a centralized data interchange format, which can be accessed by many types of systems. Many old computer systems (called legacy systems) contain data in disparate formats. System converters are being written to allow many of these to both read and output XML. Thus, data in an XML file produced by one of these legacy systems could be easily entered into other legacy systems, published on the Web, or used by any XML-aware application. Using XML as an intermediary format facilitates data exchange among systems that ordinarily are incompatible.


XML Is About Data

If HTML is about displaying information, XML is about describing information. XML is a standard language that structures and describes data and is also understood by different applications. The power of XML is its ability to separate the user interface from the data. Let's take a look at a simple XML document (chap 21\email.xml on the companion CD) to see how this works.

   <?xml version="1.0"?>
   <EMAIL>
     <TO>Bill_Pardi@hotmail.com</TO>
     <FROM>Eric_Schurman@hotmail.com</FROM>
     <CC>DHTML_in_Action@hotmail.com</CC>
     <SUBJECT>Basic email</SUBJECT>
     <BODY>This is an XML-based email.</BODY>
   </EMAIL>

What is important to notice in this example is that nothing in the document indicates how the data should be displayed. In other words, no formatting information (such as bold or italic fonts, text indent, and font size) is included. Because the document code describes what the data is, a reader can easily understand the content and structure of the document.

XML documents are also known as self-describing. That is, each document contains the set of rules to which its data must conform. Because any set of rules can be reused, it is easy for authors to create new versions of the same class of document.

NOTE
The class concept was borrowed from object-oriented programming, in which a class is used to describe a group of objects with a common set of characteristics. Classing documents provides a powerful way to group documents based on the kind of content they contain.

Valid and Well-Formed XML

Two valuable features of XML are its ability to provide structure to documents and its ability to make data self-describing. For these features to work, however, structural and grammatical rules must be in place. The next two sections give an overview of two terms, valid and well-formed, which describe documents that obey the structural and grammatical rules that govern XML.

Valid Documents

The XML processor helps enforce structure and content rules in an XML document. These rules include those required by the standard XML specification, as well as any special rules defined for that document. This second set of rules comes in the form of a Document Type Definition (DTD). A DTD is separate from the actual data in an XML document and can exist either as part of the XML document or in a separate document. A valid XML document strictly obeys both types of these rules. This book does not detail how DTDs are created and used because it focuses on simple examples that do not use DTDs. You can find out more about DTD creation from any good XML reference book or Web site, including XML in Action by William J. Pardi (Microsoft Press, 1999) and www.w3.org/xml. As you will see, however, DTDs are not always required for XML documents.

If the processor finds any errors in the XML document, it reports them to the XML application. The process of reading the DTD, checking the document against it, and reporting violations is known as validating the document. Because all of this processing and checking takes time, and because validation is not always necessary, XML supports the notion of the well-formed document. A document that meets the criteria for well-formedness is not checked for validity and is therefore processed faster.

Well-Formed Documents

The rules for well-formed documents are not nearly as strict as those governing valid documents. Creation of a well-formed document is fairly easy and intuitive. The following list outlines the core rules of well-formedness. Examples follow later in this chapter.

  • There is exactly one root element (also called the Document element).

  • No part of the root element can appear in the content of any other element in the document.

  • For all other elements in the document, both the start and end tags must be nested at the same level of the document. That is, if the start tag is placed in the content of one element, the end tag is placed in the content of that same element.

If the XML document doesn't conform to these specifications, the processor will report the errors. In Internet Explorer, the errors can be accessed with script through the Object Model. Error handling is covered in greater detail later in the chapter.

Let's look at a sample XML document:

<?xml version="1.0"?>
<PLANT>
  <COMMON>Columbine</COMMON>
  <BOTANICAL>Aquilegia canadensis</BOTANICAL>
</PLANT>

This document contains the PLANT element as the single Document element, and the Common and Botanical elements are nested inside the Document element. To illustrate this concept, the following example is not well-formed XML because it contains two elements at the root:

<?xml version="1.0"?>
<COMMON>Columbine</COMMON>
<BOTANICAL>Aquilegia canadensis</BOTANICAL>

Element nesting sets up parent/child relationships. Every child element (an element that is not the root element) resides within its parent element, similar to the Dynamic HTML Object Model discussed in Chapter 5. This can be represented as follows:

<ROOT>
 <PARENT1>
   <CHILD1></CHILD1>
   <CHILD2></CHILD2>

 </PARENT1>
</ROOT>

A child element is never located within any of its parent's other children. For example, the following code is not well-formed XML:

<ROOT>
 <PARENT1>
   <CHILD1>
   <CHILD2></CHILD1></CHILD2>
 </ROOT>
</PARENT1>

Also, no part of the Document element can reside within any of its children. This code, for example, is not considered well-formed XML:

<ROOT>
 <PARENT1>
   <CHILD1></CHILD1>
   <CHILD2></CHILD2>
 </ROOT>
</PARENT1>

As you can see, XML documents are highly structured and must follow strict but simple rules to be well-formed and valid. This structure imposes a specific hierarchical order that results in a "family tree" of parent/child elements.


XML and Internet Explorer

So far, we've seen that XML is about data, not the display of data. A logical question is then, How do I display XML data on my Web pages? Internet Explorer includes several objects that can be used when working with XML, the most common of which is the DOMDocument object. This object essentially acts as a middle layer between the data and the display portions of Internet Explorer.

When this object parses a document, it creates in memory a treelike structure of all the elements included in the document. It also provides access to the XML Document Object Model, an interface that allows access to the XML data. The object model exposes properties, methods, events, and the actual content (data) contained in the data tree. Details about the properties, methods, and events of the XML Document Object Model can be found later in this chapter in Tables 21-1 through 21-3. The object model lets authors view all parts of the tree, from roots to branches.

Code Listing 21-1 is a simple Web page that pulls data from an XML document and then displays it on screen. Figure 21-1 displays the results of this code.

Code Listing 21-1.

<HTML>
<HEAD>
<TITLE>Code Listing 21-1</TITLE>
<SCRIPT LANGUAGE="JavaScript" FOR="window" EVENT="onload">
  start()
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript">
  var xmlDoc=new ActiveXObject("Microsoft.XMLDOM")
  xmlDoc.async=false
  xmlDoc.load("email.xml")

function start(){
  var root=xmlDoc.documentElement
  todata.innerText=root.childNodes.item(0).text
  fromdata.innerText=root.childNodes.item(1).text
  ccdata.innerText=root.childNodes.item(2).text
  subjectdata.innerText=root.childNodes.item(3).text
  bodydata.innerText=root.childNodes.item(4).text
}
</SCRIPT>
</HEAD>
<BODY>
 <B>To:</B><SPAN ID="todata"></SPAN><BR>
 <B>From:</B><SPAN ID="fromdata"></SPAN><BR>
 <B>CC:</B><SPAN ID="ccdata"></SPAN><BR>
 <B>Subject:</B><SPAN ID="subjectdata"></SPAN><BR>
 <B>Body:</B><SPAN ID="bodydata"></SPAN><BR>
</BODY>
</HTML>

Figure 21-1. A sample HTML page that has processed an XML document.

The first script block at the top of the HEAD is simply an event handler that calls the start function when the page has finished loading. We'll get to this function a little later. Note that the page itself contains SPAN tags that will be the eventual target of our XML data.

As mentioned earlier, the XML processor acts as the middle layer between the XML document and the HTML page (or any other application, for that matter). We need to load the XML processor as an object on our Web page so that we can interact with it through script.

var xmlDoc=new ActiveXObject("Microsoft.XMLDOM")
xmlDoc.async=false
xmlDoc.load("email.xml")

This code first loads the DOMDocument object and assigns it to the variable xmlDoc. This provides access to the XML processor and object model. The next line tells the processor not to load any documents asynchronously. This just means that the Web page will wait until the data in the document has been loaded before continuing. The value of true causes the data to be loaded in tandem with the rest of the page, meaning that some type of detection (usually testing the ondataavailable or onreadystatechange events or the readyState property) must be used to ensure that the data is loaded before it is used. The third line causes the object to load the XML file named email.xml, shown at the start of this chapter. The beginning of the data tree that is loaded can be represented as follows.

DOCUMENT
|---XMLDECL
|   |---ATTRIBUTE version "1.0"
+---ELEMENT EMAIL
    |---ELEMENT TO
    |   +---PCDATA "Bill_Pardi@hotmail.com"

The tree begins with the Document object, which contains an XML declaration, and then the root element EMAIL. The EMAIL element contains further elements, of which the TO element is shown above. The value of the TO element is Bill_Pardi@hotmail.com, which is of the XML data type called PCDATA.

Once the page loads, the start function is called. This function is fairly straightforward. The first line of the function creates a variable named root and assigns to it the root node of the XML document. This gives us access to the base of the XML data tree. The next line of code assigns some text to the innerText property of the todata SPAN, which causes that text to display. The text it uses comes from the first child of the root XML element. It gets this text by accessing the first of the children of the root element with the code root.childNodes.item(0).text.

NOTE
If you understand this code, you will understand how to instantiate the XML DOMDocument control, load an XML document, and get data from the tree. These are the basics upon which all other XML document processing is built.

Though the document above took more work to create than the simple HTML equivalent, some useful benefits can be realized by using XML. The biggest is that a Web page can become a template for data. The HTML page created above can be used as a template for any XML content that fits that predefined model. Although creating the HTML page took some work, it can be used over and over with different content. For example, the XML document could be translated into another language, such as French or German, and still be plugged into the same HTML template.

There are other ways to get XML data into a Web page than just the DOMDocument object, such as the XML Data Source Object, XSL, and XSL Patterns. These techniques add more benefits to the use of XML for structuring and storing data. You can find out more about these on the SBN Workshop Web site and on the CD that accompanies this book. On the CD see XML (Extensible Markup Language), and choose any topic from the XML TOC (XML Table of Contents). To get to the online version, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm, or open the file named MSDN_OL.htm on the companion CD, and choose XML (Extensible Markup Language). The following tables describe aspects of the XML Document Object Model.

Table 21-1 XML Document Properties

Property | Description
async | Returns a Boolean value specifying whether asynchronous download is allowed. Value is true if asynchronous download is permitted, false if not. Read/Write.
attributes | Returns an object containing a list of attributes for the current node. If the node cannot contain attributes, null is returned. Read-only.
childNodes | Returns an object containing a node list of all the available children of the current node. If the node does not contain children, null is returned. Read-only.
doctype | Returns an object containing the document type node holding the DTD for the current document. If the document does not contain a DTD, null is returned. Read-only.
documentElement | Returns an object that contains the data in the root Document element. If the document does not contain a root, null is returned. Read/Write.
firstChild | Returns an object containing the first child element of the current node. If the node does not contain a first child element, null is returned. Read-only.
implementation | Returns the Document Object Model (DOM) implementation object for the current XML document. Read-only.
lastChild | Returns an object containing the last child element of the current node. If the node does not contain a last child element, null is returned. Read-only.
nextSibling | Returns an object containing the next sibling in the child list of the current document node. If the node does not contain a next sibling node, null is returned. Read-only.
nodeName | Returns a string representing the qualified name of the current node (element, attribute, or entity reference). Read-only.
nodeType | Returns a number representing the DOM type (element, attribute, text) of the current node. Read-only.
nodeValue | Returns the text associated with a specified node. This is not the value of the data in an element, but rather unparsed text that might be associated with a node, such as an attribute or a processing instruction. Returns null for nodes of certain types. Read/Write.
ondataavailable | Specifies an event handler for the ondataavailable event. Write-only.
onreadystatechange | Specifies an event handler for the onreadystatechange event. Write-only.
ownerDocument | Returns an object containing the root node for the document containing the current node. Read-only.
parentNode | Returns an object containing the parent node of the current node. If the node does not exist in the tree, null is returned. Read-only.
parseError | Returns a DOM parse error object that describes the last parse error. If no error has occurred, 0 is returned. Read-only.
previousSibling | Returns an object containing the sibling node that occurs just before the current node. If the node does not contain a previous sibling node, null is returned. Read-only.
readyState | Returns a number representing the current state of the XML document data. Read-only. Values are as follows: 0 (uninitialized) XML object is created but no document is loaded. 1 (loading) Load in progress, but parsing has not yet started. 2 (loaded) Some of the document is loaded and parsing has begun, but the object model is not available. 3 (interactive) Object model is available for loaded portions of the document. 4 (completed) Document completely loaded. This does not necessarily mean the load was successful.
url | Returns the URL for the last document that was loaded successfully. If the document exists only in memory (it was not loaded from an external file), null is returned. Read-only.
validateOnParse | Indicates to the parser whether the document should be validated. If true, the document is validated when it is parsed. If false, the document is not validated and is expected only to be well-formed. Read/Write.
xml | Returns the XML representation of the specified node and any descendants. Read-only.

Table 21-2 XML Document Methods

Method | Description
abort() | If this method is called during an asynchronous download, all parsing is stopped and any portion of the document in memory is discarded.
appendChild(newChild) | Appends a node as the last child of the specified node.
cloneNode(deep) | Creates an exact replica of a specified node. The deep parameter is a Boolean value. If true, the node is cloned with all of its descendants. If false, only the specified node and its attributes are cloned.
createAttribute(name) | Creates an attribute with a specified name.
createCDATASection(data) | Creates a CDATA section that contains the specified string data.
createComment(data) | Creates a comment that contains the specified string data.
createDocumentFragment() | Creates a new document fragment but does not add it to the document tree. To add it to the tree, an insert method must be used, such as insertBefore, replaceChild, or appendChild.
createElement(tagname) | Creates an element with the specified (case-sensitive) tag name.
createEntityReference(name) | Creates a new entity reference with the specified name, but does not add it to the document tree. To add it to the tree, an insert method must be used, such as insertBefore, replaceChild, or appendChild.
createNode(type, name, nameSpaceURL) | Creates a new node with the specified type, name, and namespace.
createProcessingInstruction(target, data) | Creates a new processing instruction containing the specified target and data, but does not add it to the tree. To add it to the tree, an insert method must be used, such as insertBefore, replaceChild, or appendChild.
createTextNode(data) | Creates a new text node containing the specified data, but does not add it to the tree. To add it to the tree, an insert method must be used, such as insertBefore, replaceChild, or appendChild.
getElementsByTagName(tagname) | Returns a collection of elements with the specified name. Using the tagname "*" returns all the elements found in the document.
hasChildNodes() | Returns true if the node has children, false otherwise.
insertBefore(newChild, refChild) | Inserts a new child node before a reference node. The newChild parameter is an object containing the address of the new child node, while refChild is the address of the reference node. If the refChild parameter is not included, the new child is inserted at the end of the child list.
load(url) | Loads the indicated document from the specified location. Returns true if the document loads successfully, false otherwise.
loadXML(xmlString) | Loads an XML document or fragment from a string. Returns true if the document loads successfully, false otherwise.
nodeFromID(idString) | Returns a node for which the node ID matches the specified value. If a match is found, an object is returned. If the operation fails, null is returned.
parsed() | If the current node and all its descendants have been parsed and instantiated, true is returned. If any part of the node has not yet been parsed, false is returned.
removeChild(child) | Removes the specified child node from the node list. The child parameter is an object containing the child node to be removed.
replaceChild(newChild, oldChild) | Replaces the specified old child node with the supplied new child node. If newChild is null, the old child is removed without a replacement.
selectNodes(patternString) | Returns a node list object containing nodes that match the supplied XSL pattern.
selectSingleNode(patternString) | Returns the first node that matches the supplied XSL pattern. If no matches are found, null is returned.
transformNode(stylesheet) | Returns a string containing the result of processing the current node and its child nodes using the supplied XSL style sheet.

Table 21-3 XML Document Events

Event | Description
ondataavailable | The ondataavailable event is fired as soon as any data is available. This technique does not indicate how much of a given document is available.
onreadystatechange | The onreadystatechange event is fired when the readyState property changes, but the event does not indicate what the ready state is. Use the readyState property to get the current state.


Beyond the Basics -- More Scripting Techniques

Beyond the Basics—More Scripting Techniques

The simple email sample file shown above demonstrates how you can access the XML object model and work with XML data. A closer look at the document and its scripts reveals that simplicity comes at a cost. In an effort to keep the scripts on the easy side, some techniques have been incorporated that would prove to be less than ideal in many situations. Consider the following:

  • The script code that accesses the XML document tree and extracts the data assumes that we know not only how many elements exist but that the order of the elements is the same as in our original, since we address each one by index. While this type of code might work in some applications, it would be totally inadequate in others.

  • The script code addresses each element separately. While this might work fine for small documents, it would become tedious and potentially error-prone in large or complex documents.

  • The HTML document is not totally data-independent. The HTML tags used for layout and formatting contain text (such as To: and From:). If this document needed to be translated into other languages, it would require that both the XML document and the HTML document be edited.

We will now look at some scripting techniques that will help us avoid some of the issues just described.

Walking the XML Document Tree

While in the previous example the author was required to know the number and type of elements in the XML document, this situation can be easily avoided by using some other properties and methods in the XML object model.

One of these useful properties is childNodes, which returns a list of the children of the current node. The length property of childNodes contains the number of children. Thus, it is pretty easy to step through the children of a node, as demonstrated in Code Listing 21-2.

Code Listing 21-2.

<HTML>
<HEAD>
<TITLE>Code Listing 21-2</TITLE>
<SCRIPT LANGUAGE="JavaScript">
  var xmlDoc=new ActiveXObject("Microsoft.XMLDOM")
  xmlDoc.async=false
  xmlDoc.load("email.xml")
  root = xmlDoc.documentElement

  for (var i=0; i<root.childNodes.length; i++){
    alert(root.childNodes.item(i).nodeName+" = "+
          root.childNodes.item(i).text)
  }
</SCRIPT>
</HEAD>
</HTML>

Figure 21-2. A dialog box containing the name and contents of the first element.

Loading the HTML file now should produce a series of five dialog boxes that each contain the name of an element in the XML document and its contents. The first one should look like Figure 21-2. The preceding code uses the property root.childNodes.length to ask the XML document how many child elements the root element contains. The script then enters a loop and goes through all the children of the root element, getting the name of each child node (with the nodeName property) and the text contained in each node until the last one is reached.

However, this code just walks one level of the tree. If any of the children of the root element had children of their own, they would have been ignored by Code Listing 21-2. The inbox.xml file is an example of a more complicated document (shown on the following page and in chap21\inbox.xml on the companion CD) in which there are multiple levels to the tree. Note that the first email even contains an element (CC) not found in the other emails.

<?xml version="1.0"?>
<INBOX>
 <EMAIL>
   <TO>Bill_Pardi@hotmail.com</TO>
   <FROM>Eric_Schurman@hotmail.com</FROM>
   <CC>DHTML_in_Action@hotmail.com</CC>
   <SUBJECT>My document is a tree.</SUBJECT>
   <BODY>This is an example of a tree structure.</BODY>
 </EMAIL>
 <EMAIL>
   <TO>Bill_Pardi@hotmail.com</TO>
   <FROM>Eric_Schurman@hotmail.com</FROM>
   <SUBJECT>XML is cool.</SUBJECT>
   <BODY>This is a simple message.</BODY>
 </EMAIL>
 <EMAIL>
   <TO>Bill_Pardi@hotmail.com</TO>
   <FROM>Eric_Schurman@hotmail.com</FROM>
   <SUBJECT>Here is that code.</SUBJECT>
   <BODY>I send too many emails.</BODY>
 </EMAIL>
</INBOX>

This requires more sophisticated script to get the same type of results that we found in Code Listing 21-1, in which the contents of the email were displayed in the browser. Code Listing 21-3 starts at the beginning of the XML document and then progressively walks down the tree and displays the contents of each node. If a node has children, they are visited and their contents are displayed. Figure 21-3 shows the results of running this code.

Code Listing 21-3.

<HTML>
<HEAD>
<TITLE>Code Listing 21-3</TITLE>
<SCRIPT LANGUAGE="JavaScript">
  var xmlDoc = new ActiveXObject("microsoft.xmldom")
  xmlDoc.async=false
  xmlDoc.load("inbox.xml")
  root=xmlDoc.documentElement
  newHTML=""

function start(){
  buildTree(root)
  content.innerHTML=newHTML
}

function buildTree(passedNode){ var children = passedNode.childNodes.length
  for (var j=0; j<children; j++){
    Node=passedNode.childNodes.item(j)
    if (Node.nodeName=="EMAIL"){ newHTML+=("<P>"+Node.nodeName+" "+j) }
    if (!Node.hasChildNodes()){
      newHTML+=( "<BR><B>"+Node.parentNode.nodeName+":</B> "+Node.text )
    }
    buildTree(Node)
  }
}
</SCRIPT>
</HEAD>
<BODY onload="start()">
<SPAN ID="content"></SPAN>
</BODY>
</HTML>

Click to view at full size.

Figure 21-3. Displaying the XML document content.

Let's walk through this code. When the page is loading, the script block loads the XML file, assigns the XML document element to the variable root, and creates the empty newHTML variable, which is used later in the script. When the page finishes loading, the onload event handler in the BODY tag calls the start function, which in turn calls the buildTree function, passing it the root XML element.

The majority of the work in this sample is accomplished in the buildTree function. This is a recursive function; that is, it calls itself when certain conditions are met. This function essentially looks at the current node and checks to see how many children it has. If it has children, the function calls itself again, passing itself the first of the children. Once it reaches a node with no children, it adds to the newHTML variable some HTML code describing the data in the current node, and then it returns to the parent node. By repeating this, it can travel across the entire data tree. Let's take a look at parts of the function in depth.

var children = passedNode.childNodes.length
for (var j=0; j<children; j++){

The beginning of the function finds out how many children the current node has and assigns that value to the children variable. The next line starts a for loop that will be repeated for each child of the current node.

Node=passedNode.childNodes.item(j)
if (Node.nodeName=="EMAIL"){ newHTML+=("<P>"+Node.nodeName+" "+j) }
if (!Node.hasChildNodes()){
  newHTML+=( "<BR><B>"+Node.parentNode.nodeName+":</B> "+Node.text )
}

Next the current child is assigned to the variable Node. We would like each one of the emails in our data to be separated. This is accomplished by the second line above. If the Node is named EMAIL, that line adds a paragraph tag to newHTML in addition to the node's name and the number of this email. We could have also tested whether Node.parentNode==root, because the only elements just below the root are EMAIL elements.

buildTree(Node)

The final line of the for loop calls the buildTree function again, passing it Node. Ultimately, the function is called for every item in the XML data tree. A much more flexible and full-featured XML tree walker can be found at microsoft.com/gallery/samples/xml/tree_viewer/default.asp or on the companion CD. See Tools and Samples; samples; XML; and XML Tree Viewer.

Note that while using these techniques can make an HTML document much more flexible and powerful, the document is still only a template for a specific class of XML document or documents. This makes HTML and XML perfect complements to one another.

Error Handling

The XML object model provides several ways for authors to handle errors when they occur as a result of the XML document. One of these is the Document object's parseError property, which provides information about problems that occur in an XML document so that authors can deal with them and users might not have to.

The parseError property provides a code for every error that might occur. An author can use these codes to:

  • Help debug XML documents or scripts

  • Inform the user of problems and provide suggestions for resolution

  • Trap for certain kinds of errors and fix them behind the scenes

The sample code below shows how the parseError property might be used to inform a user of a problem.

var xmlDoc = new ActiveXObject("microsoft.xmldom");
xmlDoc.load("email.xml");

if (xmlDoc.parseError.reason == ""){
  alert("Document loaded successfully")
}
else{
 alert("The following error occurred: "+xmlDoc.parseError.errorCode)
}

This technique can be used both for debugging and for shielding users from errors.


XML Data Islands

In the examples above, we worked with XML as the data source and HTML as the display mechanism. They were kept as separate documents that interacted when the HTML file was viewed. Another option is to use XML data islands. Data islands allow authors to include XML fragments directly in an HTML document. There are pros and cons to this approach. On the plus side:

  • You don't need a separate XML file.

  • You don't need to load the XML data through script.

  • You don't need to instantiate the Microsoft ActiveX control through the use of the OBJECT element or ActiveXObject.

There can also be some negatives, depending on how the data island is used:

  • The XML data is no longer independent of the HTML file.

  • The XML data is not very portable to other applications or HTML pages.

  • The XML might be more difficult to manage if it is interspersed with HTML code.

XML data islands can be either inline XML or linked XML documents.

Working with Inline XML Data Islands

To use inline XML data islands, you simply insert XML code directly into an HTML page. The XML "document" is contained inside a set of <XML></XML> tags. To demonstrate this, we'll modify Code Listing 21-1 by embedding email.xml into it and changing the code somewhat, as shown in Code Listing 21-4. This will produce the exact same output as the earlier example, shown in Figure 21-1.

Code Listing 21-4.

<HTML>
<HEAD>
<TITLE>Code Listing 21-4</TITLE>

<XML ID="email">
 <EMAIL>
   <TO>Bill_Pardi@hotmail.com</TO>
   <FROM>Eric_Schurman@hotmail.com</FROM>
   <CC>DHTML_in_Action@hotmail.com</CC>
   <SUBJECT>Basic email</SUBJECT>
   <BODY>This is an XML-based email.</BODY>
 </EMAIL>
</XML>

<SCRIPT LANGUAGE="JavaScript">
function start(){
  xmlDoc=email

  var root=xmlDoc.documentElement
  todata.innerText=root.childNodes.item(0).text
  fromdata.innerText=root.childNodes.item(1).text
  ccdata.innerText=root.childNodes.item(2).text
  subjectdata.innerText=root.childNodes.item(3).text
  bodydata.innerText=root.childNodes.item(4).text
}
</SCRIPT>
</HEAD>
<BODY onload="start()">
 <B>To:</B><SPAN ID="todata"></SPAN><BR>
 <B>From:</B><SPAN ID="fromdata"></SPAN><BR>
 <B>CC:</B><SPAN ID="ccdata"></SPAN><BR>
 <B>Subject:</B><SPAN ID="subjectdata"></SPAN><BR>
 <B>Body:</B><SPAN ID="bodydata"></SPAN><BR>
</BODY>
</HTML>

First note that while the inline XML data is enclosed in <XML> tags, the <XML> element is not the root node of the data. Instead, it is an HTML tag that identifies to the browser that whatever is contained inside it should be treated as XML. Notice also that the <XML> tag has an ID assigned to it so that it can be accessed by script. The new code xmlDoc=email is the equivalent of instantiating an XMLDOM ActiveXObject and then loading a particular XML document. In fact, the same processor is being used; this is just a different way of accessing it. In addition to the inline data island, there is another way to use the <XML> tag—by linking to an external XML document.

Working with Linked XML Data Islands

To link the <XML> tag to an XML document, you simply use the SRC attribute of the <XML> tag. We can replace the entire XML element in the previous document with the following line of code.

<XML ID="email" SRC="email.xml"></XML>

This works exactly like the preceding example. The advantage here is that the XML data remains separate from the HTML document. In essence, this method works very much like using the ActiveX control method, except that the browser takes the responsibility for instantiating the control and loading the document.

Attributes of the <XML> Tag

The <XML> tag includes some additional attributes that provide more control over what happens when the document is loaded.

The VALIDATEONPARSE attribute indicates whether the document should be validated when it is parsed. Its default value is true. It is used as shown below:

<XML ID="xmlDoc" SRC="xmldoc.xml" VALIDATEONPARSE="false"></XML>

The ASYNC attribute indicates whether the document should be downloaded asynchronously. Its default value is true. Usage is shown in the sample below:

<XML ID="xmlDoc" SRC="xmldoc.xml" ASYNC="false"></XML>

Is XML the solution to all the problems that have plagued the Web, or is it all just hype? It really isn't either one. XML is receiving industry-wide support for many different uses, not just the Web. It shows a lot of promise, especially if XML support spreads to different browsers. This chapter has provided only a very simple overview of XML. Find out more about XML at the W3C Web site at www.w3.org or in a good XML reference book, such as XML in Action by William J. Pardi (Microsoft Press, 1999).


Chapter 22 -- Additional Possibilities

 Chapter 22

Additional Possibilities

This chapter covers a variety of topics we consider important: general support for ActiveX controls, scriptlet technology, behaviors, cookies, HTML applications, channels, and ratings systems. Although space limitations do not allow a complete discussion, we will present general information on each subject.


Working with ActiveX Controls

Microsoft Internet Explorer has supported the use of ActiveX controls since version 3.0, and the majority of modern development environments (like Microsoft Visual InterDev and Microsoft Visual Basic) make adding ActiveX controls to other Windows programs easy for developers. Although no current version of Netscape Navigator directly supports ActiveX, a plug-in from NCompass Labs Inc. (found at www.ncompasslabs.com) adds a level of ActiveX support to Netscape Navigator.

ActiveX controls are essentially traditional programs (written in C++ or Visual Basic, for example) that adhere to a certain set of standards. These programs can be used within other programs, most commonly browsers, to add functionality that would not otherwise be available. Many of the built-in controls referred to throughout this book are ActiveX controls—the tabular data control and the Structured Graphics control, for example. In addition to the built-in controls, thousands of other controls are available from Microsoft and many other companies.

No matter where the controls come from, the process of incorporating them into a Web page is basically the same. You can include either a built-in control or a third-party control by using the OBJECT element.

NOTE
To let users of the NCompass ScriptActive plug-in for Netscape Navigator access ActiveX controls on a Web page, a developer must do more than just use OBJECT elements. This plug-in (like all plug-ins) must be activated with an <EMBED> tag. NCompass provides tools that assist in the conversion of pages that use standard <OBJECT> tags so that they also include <EMBED> tags. For more information about getting a Web site to work under ScriptActive, consult the NCompass Labs Web site at www.ncompasslabs.com.

Anatomy of an OBJECT

When you include a third-party ActiveX control in your Web page, you enclose the control in <OBJECT> tags, just as you do for a built-in control. When a control is not already available on a client's system, however, additional information is necessary, as shown in Code Listing 22-1. This code sets up a popular ActiveX control, the Macromedia Flash control. This software is available as a Netscape plug-in, so the listing also uses an <EMBED> tag.

Notice the CODEBASE attribute in Code Listing 22-1. Internet Explorer allows software to be downloaded and installed based on the setting of this attribute, which, in this instance, specifies the location (URL) of a CAB file. A CAB file is a single compressed file that contains all the files necessary to install the ActiveX control on the user's computer. If the Web page is opened on a computer that does not have the ActiveX control already installed, the CAB file is (at the user's discretion) downloaded, extracted, and installed. The page can then load and run normally.

Code Listing 22-1.

<HTML>
<HEAD>
<TITLE>Listing 22-1</TITLE>
</HEAD>
<BODY>
<OBJECT CLASSID="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
  CODEBASE="http://active.macromedia.com/flash2/cabs/
    swflash.cab#version=3,0,0,0" [Must be on previous line]
  ID=INDEX WIDTH=95% HEIGHT=95%>
  <PARAM NAME="movie" VALUE="myFile.swf">
  <PARAM NAME="loop" VALUE="false">
  <PARAM NAME="quality" VALUE="high">
<EMBED SRC="myFile.swf" LOOP="false" QUALITY="high" SWLIVECONNECT="false"
  WIDTH="95%" HEIGHT="95%" TYPE="application/x-shockwave-flash"
  PLUGINSPAGE="http://www.macromedia.com/shockwave/download/
    index.cgi?P1_Prod_Version=ShockwaveFlash"> [Must be on previous line]
</EMBED>
</OBJECT>
</BODY>
</HTML>

At the end of the CODEBASE setting, you see version information. The computer uses this information to compare the control it already has (if any) to the version available for downloading to ensure that it will be using the latest version. For this process to work, the CAB file must be built properly and the specified location must be correct.

Other than the inclusion of the additional information in the CODEBASE setting, the OBJECT element works the same for both built-in and external controls. Most controls have their own attributes, properties, and methods that can be set at design time or accessed through scripts. It is up to the developer of the control to provide the details about how to use it.


Scriptlets

Scriptlets are essentially small Web pages that can be used as components in other Web pages or applications. They conform to a set of standards that provide a standardized way for the page or application that is hosting the scriptlet to access the properties, methods, and other content that the developer makes explicitly available. Scriptlets can be used by any application that supports ActiveX controls. (DHTML Behaviors, covered later in this chapter, are similar to scriptlets but offer improved flexibility and backward compatibility.)

One advantage of using a scriptlet is that you are creating a reusable code module that you can incorporate into other Web pages. For example, suppose you are developing a Web site whose pages all contain user interface (UI) components (such as a toolbar or a button bar) that look alike but behave differently, depending on where they are used. You might create the UI components as a scriptlet and then access the appropriate properties or methods required for each page.

NOTE
Internet Explorer versions 4.0 and later support scriptlets on all platforms, including Windows, Macintosh, and UNIX. No version of Netscape Navigator currently supports scriptlets. If you try to view a page containing a scriptlet in Navigator, the page is simply rendered without the scriptlet.

Adding a scriptlet to a Web page is accomplished by simply creating an appropriately sized <OBJECT> tag with a TYPE attribute of text/x-scriptlet and a DATA attribute that contains a URL pointing to the target scriptlet, as the following code demonstrates.

<OBJECT TYPE="text/x-scriptlet"
  WIDTH="50" HEIGHT="80" DATA="myfile.htm">
</OBJECT>

Creating a scriptlet is also simple—it is simply a Dynamic HTML page. All you need is a basic understanding of Dynamic HTML and scripting (and since you are this far along in this book, you have a fair amount of experience with both). In Code Listing 22-2, we have created an HTML page that we will use as a scriptlet in another page. The browser displays this page as a line of text. Note that even though the page contains script, no mechanism exists to call that script.

Code Listing 22-2.

<HTML>
<HEAD>
<TITLE>Listing 22-2</TITLE>
<SCRIPT LANGUAGE="JavaScript">

function public_chngText(sNum, sText){
  label.innerHTML=""
  for (var i=1; i<=sNum; i++){
    label.innerHTML+="<SPAN STYLE=`font-size:"+i*5+"`>"+sText+" </SPAN>"
  }
}
</SCRIPT>
</HEAD>
<BODY BGCOLOR="#CCCCCC">
<B><SPAN ID="label">Text</SPAN></B>
</BODY>
</HTML>

To use functions and properties from a scriptlet in the container HTML page, you must identify them as public. There are two ways to do this: by creating a public_description object or by prefacing item names with the text public_. In Code Listing 22-2, we use the second method, as in public_chngText. Any page that hosts the scriptlet can then refer to the item through dot notation as though it were a child item of the scriptlet—for example, myScriptlet.chngText. The public_ prefix is excluded when accessing the item from the host page.

Another option is to create a public_description object that holds all aspects of the scriptlet that we want to be accessible. These are very similar to constructor functions in JScript (discussed in Chapter 8). This approach is convenient because all public parts of the scriptlet can be found in one location. We could have created a public_description object for Code Listing 22-2 as follows:

var public_description=new InitScriptlet()

function InitScriptlet() {
  this.bgcolor=document.bgColor
  this.chngText=chngText
}

If we had used this public_description object, we would have had access to the background color of the scriptlet in addition to the chngText function. Prefacing functions and properties with public_ is not necessary when using a public_description object.

Code Listing 22-2 includes a JScript function that repeats a specified bit of text a specified number of times on screen and increases the size of the text with each repetition. When this page is displayed by itself, the user sees only the default text that is coded in the SPAN element, Text. Because the script is not activated, the default text is not changed.

Code Listing 22-3 invokes the scriptlet in three places, using the OBJECT element. Figure 22-1 shows the results.

Code Listing 22-3.

<HTML>
<HEAD>
<TITLE>Listing 22-3</TITLE>
</HEAD>
<BODY>
<OBJECT ID="TextRepeater" WIDTH="500" HEIGHT="100"
  TYPE="text/x-scriptlet"  DATA="lst22-2.htm">
</OBJECT><P>
<FORM NAME="F1">
Number of repeats: <INPUT TYPE="Text" NAME="repeats" VALUE="1" SIZE="1">
Display text: <INPUT TYPE="text" NAME="newtext" VALUE="Text">
<INPUT TYPE="button" VALUE="Change"
  ONCLICK="TextRepeater.chngText(F1.repeats.value, F1.newtext.value)">
</FORM>
<OBJECT ID="TextRepeater2" WIDTH="200" HEIGHT="100" ALIGN="left"
  TYPE="text/x-scriptlet"  DATA="lst22-2.htm"></OBJECT>
<OBJECT ID="TextRepeater3" WIDTH="275" HEIGHT="100"
  TYPE="text/x-scriptlet"  DATA="lst22-2.htm"></OBJECT>
<SCRIPT FOR="window" EVENT="onload" LANGUAGE="JavaScript">
  TextRepeater2.chngText(4, `Sample')
  TextRepeater3.chngText(6, `Code')
</SCRIPT>
</BODY>
</HTML>

Click to view at full size.

Figure 22-1. The button created on the second page allows the public function to be called from outside the scriptlet.

In Code Listing 22-3, the first instance of the scriptlet loads in its default state. Two text fields and a button allow the content of this first scriptlet to be changed by the user. The second two instances of the scriptlet are changed as soon as the page is loaded, through the script block at the end of the listing. (The block could have gone in the header with the same result.) This script block calls the chngText function of each scriptlet to specify text and the number of repeats.

A scriptlet can pass events to the host page by calling window.external.bubbleEvent(). This method simply passes the current event to the host. Scriptlets can pass custom events through the window.external.raiseEvent method and also let you create your own context (right-click) menus. You can learn more about custom events, context menus, and scriptlets as a whole at the SBN Workshop Web site. On the companion CD, see Workshop (References); Component Development; DHTML Scriptlets. Online, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm, or open the file named MSDN_OL.htm on the companion CD, and choose DHTML Scriptlets.


Behaviors

Because both script and content typically live together on a Web page, functionality can be broken inadvertently by writers and editors who are working on content. DHTML Behaviors provide a way to separate functionality from the content that it affects.

DHTML Behaviors can be created both with HTML Components (HTCs) and with traditional programming languages such as C++. We will focus on the use of HTCs, as C++ is beyond the scope of this book. (Find out more about using C++ to implement behaviors from the SBN Workshop. On the companion CD; see Workshop (References); DHTML, HTML, and CSS; DHTML Behaviors; C++ Reference.) HTCs are essentially standard HTML files containing script and some HTC-specific tags. Elements in other Web pages can then use the behavior CSS attribute to access the functionality contained in the HTC. HTCs can expose their properties, methods, and events (including custom events) to the containing page, and can in turn access the object model of the containing page. Code Listing 22-4 demonstrates a Web page containing an expanding/collapsing menu as well as methods and properties implemented through DHTML Behaviors. Figures 22-2 and 22-3 show the results.

Code Listing 22-4.

<HTML>
<HEAD>
<TITLE>Listing 22-4</TITLE>
<STYLE>
  DIV {cursor:hand;margin-left:2em}
  .ExpandingHead{behavior:url(ExpMenu.htc)}
</STYLE>
</HEAD>
<BODY>
<DIV ID="Item1" CLASS="ExpandingHead"><B>Level 1 Item 1</B>
  <DIV>Level 2 Item 1</DIV>
  <DIV>Level 2 Item 2</DIV>
    <DIV CLASS="ExpandingHead"><B>Level 2 Item 3</B><BR>
      <DIV>Level 3 Item 1</DIV>
      <DIV>Level 3 Item 2</DIV>
    </DIV>
  <DIV>Level 2 Item 4</DIV>
</DIV>
<DIV CLASS="ExpandingHead"><B>Level 1 Item 2</B>
  <DIV>Level 2 Item 1</DIV>
  <DIV>Level 2 Item 2</DIV>
</DIV>
<FORM>
<INPUT TYPE="BUTTON" VALUE="Run Item1.showChildren()"
       onclick="Item1.showChildren()">
<INPUT TYPE="BUTTON" VALUE="Display item1.iChildren"
       onclick="alert(Item1.iChildren)">
</FORM>
</BODY>
</HTML>

Notice the simplicity of the code in the body of the page. Every item in the menu is a DIV element. If a menu item DIV element contains other nested items, it is given the ExpandingHead CLASS. This class is defined in the global style sheet at the top of the page. It contains the CSS attribute behavior that is directed to the file ExpMenu.htc.

Click to view at full size.

Figure 22-2. The menu before a heading is clicked.

Click to view at full size.

Figure 22-3. Code Listing 22-4 displays fully opened in Netscape Navigator.

The file ExpMenu.htc listed below and included on the companion CD as chap22/ExpMenu.htc contains the behavior itself.

<PUBLIC:HTC URN="www.microsoft.com">
<SCRIPT language="JavaScript">
  attachEvent("onclick", toggleDisplay)
  function toggleDisplay(){
    // Hide/unhide all child objects (start at 1 so heading is skipped)
    for (var i=1; i<children.length; i++){
      children[i].style.display=(children[i].style.display==""?"none":"")
    }
    // Prevent click on sub item from collapsing whole menu
    if(window.event){window.event.cancelBubble=true}
  }
  // Collapse menu when first loaded
  toggleDisplay()

  function showChildren(){
    // Return list of child items
    var Txt=""
    for(var i=1;i<children.length;i++){Txt+=(children[i].innerText+"\n")}
    alert(Txt)
  }

  iChildren=children.length
</SCRIPT>
  <PUBLIC:METHOD NAME="showChildren" />
  <PUBLIC:PROPERTY NAME="iChildren" />
</PUBLIC:HTC>

The beginning and end tags for an HTML Component file are <PUBLIC:HTC URN =location> and </PUBLIC:HTC>. The URN attribute is used to specify a unique name for the component, which usually points to the location where the HTC is found. This attribute is helpful if you use multiple behaviors on the same element. It can be used in combination with the srcURN property of the event object to identify which behavior is acting at a particular time.

The majority of the functionality of the behavior is found in the SCRIPT block. The attachEvent method can be used to bind a function in the HTC to an event fired by the element that called the behavior. In our case, the toggleDisplay function in the behavior is bound to the onclick event on the DIV. This function toggles the contents of the DIV between being hidden and being visible when the DIV is clicked as shown in Figure 22-4.

Click to view at full size.

Figure 22-4. The menu after Level 1 Item 1 is clicked.

After the SCRIPT block in the HTC, we see two tags. They both begin with the word PUBLIC, which makes them available to the hosting page. The METHOD element exposes the showChildren function to the containing Web page. This function can then be called as though it were a method of the element that calls the behavior. In Code Listing 22-4 there are two buttons after the collapsing menu. When clicked, the first button calls Item1.showChildren(). The Item1 DIV element has the ExpandingHead class, which links it to the ExpMenu behavior. Because the behavior exposes the showChildren method, it can be called directly as a method of the Item1 object. Figure 22-5 shows the resulting Alert dialog box.

Figure 22-5. The Alert dialog box displayed when the first button is clicked.

In the SCRIPT block in the HTC, an iChildren variable is created and set equal to the number of children contained by the Web page element that called the HTC. The PROPERTY element is then used to expose this value as a property of the element in the Web page. The second button in Code Listing 22-4 accesses this property through Item1.iChildren. The PROPERTY element can also be used by the HTC to read a property set on the calling element in the Web page. For example, if the DIV element had had the property FOO="Example" the following code snippet would create in the HTC a variable named FOO that was tied to the value set in the DIV element:

<PUBLIC:PROPERTY NAME="FOO" />

Behaviors can do far more than what is outlined here; you can find extensive references for behaviors on the SBN Workshop Web site. The Workshop also contains a number of sample behaviors, such as the SoundRollover behavior, which can be applied to an element to cause a noise when the mouse passes over it.

Default Behaviors

Internet Explorer 5 includes several default behaviors that provide a number of different services to Web pages. Some are described in Table 22-1.

Code Listing 22-5 demonstrates the use of the saveFavorite behavior. If users add this page to their favorites, any elements with the saveFavorite class fire the onsave event. This event causes the text field in Code Listing 22-5 to call the setAttribute method of the behavior, saving the value of the txt1 field in the name of txt1_ssve. When the user returns to the page by going to the entry in the favorites list, the onload event of the text field is fired and the getAttribute method of the behavior is used to retrieve the saved value.

Table 22-1 Internet Explorer Default Behaviors

Name | Description
clientCaps | Contains information about the features of the end user's browser (CLIENT CAPabilitieS)
download | Allows a file to be downloaded and accessed through script and for a function to be run when the download is complete
homePage | Allows you to check and set the user's home page (with the user's permission)
saveFavorite | Allows you to control and save the state of a page when it is added to a user's favorites
saveHistory | Allows you to control and save the state of a page when the user navigates away from the page
saveSnapshot | Allows you to control the state of a page when the user saves a Web page to disk
userData | Allows information to be saved for when a user returns to a Web page and allows for more flexibility and data storage than cookies

Code Listing 22-5.

<HTML>
<HEAD>
<TITLE>Listing 22-5</TITLE>
<STYLE>
  .saveFavorite {behavior:url(#default#saveFavorite)}
</STYLE>
</HEAD>
<BODY>
Uses saveFavorite:
<INPUT ID="txt1" CLASS="saveFavorite" TYPE="text"
       onsave="this.setAttribute(`txt1_save',txt1.value)"
       onload="this.getAttribute(`txt1_save')">
</BODY>
</HTML>


Cookies

Cookies are small pieces of information stored by a user's browser on his or her machine. Although they are supported in most modern browsers, cookies are quite limited compared to the default behaviors described earlier. They cannot exceed 4 kilobytes in size, and some characters are restricted.

A cookie is accessed through the cookie property of the document object. Information typically is stored in a cookie in name=value pairs. Several other types of information can be used in cookies as well, including domain, path, and security settings and an expiration date for the cookie. The following line of script demonstrates storing a variable and an expiration date in a cookie:

document.cookie= "myGreeting=Hi; expires=Mon, 31 Dec 1999 23:59:59 UTC;"

The variable of name myGreeting is given the value of Hi. The cookie is set to expire at the end of 1999. If no value is set for expires, or if the expiration date is set to a time in the past, the cookie will be deleted as soon as the browser is closed. Code Listing 22-6 and Figure 22-6 demonstrate a more sophisticated use of cookies, including both storing and retrieving information from a cookie and displaying all names and values in a cookie.

Code Listing 22-6.

<HTML>
<HEAD>
<TITLE>Listing 22-6</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function setCookie(strName, strVal){
  // Store cookie info-escape strVal to ensure legal characters
  document.cookie=( strName+"=" + escape(strVal) +
                    "; expires=Mon, 31 Dec 1999 23:59:59 UTC;" )
}
function getCookie(strName){
  // Separate individual cookies, store in an array
  var aCookies=document.cookie.split("; ")
  for (var i=0 ; i<aCookies.length ; i++){
    // Separate name from value, store in array
    var aOneCookie=aCookies[i].split("=")
    // Return value if cookie name matches strName
    if (strName==aOneCookie[0]){ return unescape(aOneCookie[1])     }
  }
  // Return null if no cookie exists of that name
  return null
}
function showCookie(){
  strA=""
  var aCookies=document.cookie.split("; ")
  for (var i=0;i<aCookies.length;i++){strA+=(aCookies[i]+"\n")}
  alert(strA)
}
</SCRIPT>
</HEAD>
<BODY>
<FORM NAME="F1">
<B>Create New Cookie</B><BR>
New Cookie Name: <INPUT NAME="T1" TYPE="text"> <BR>
New Cookie Value: <INPUT NAME="T2" TYPE="text">
<INPUT TYPE="button" VALUE="Create"
       onclick="setCookie(F1.T1.value , F1.T2.value)"> <BR><BR>
<B>Show Named Cookie</B><BR>
Name: <INPUT NAME="T3" TYPE="text">
<INPUT TYPE="button" VALUE="Show"
       onclick="alert(`That cookie = `+getCookie(F1.T3.value))"> <BR><BR>
<B>Display Entire Cookie</B><BR>
<INPUT TYPE="button" VALUE="Display" onclick="showCookie()">
</FORM>
</BODY>
</HTML>

Click to view at full size.

Figure 22-6. This page saves and retrieves information in cookies. This screen shows what happens when the Display button is clicked after two new cookies have been created.

The user can create a cookie by typing a name in the New Cookie Name field and a value in the New Cookie Value field and clicking Create. These steps run the setCookie function, which takes a name and value and commits them to the cookie. The user can retrieve a particular name=value pair from the cookie by typing the cookie name in the Name field and clicking Show. This step runs the getCookie function, which splits the cookie up into its separate name=value pairs and compares each name to the value of the Name field. When it finds one that matches, it returns the value of that name=value pair. The entire contents of the cookie can be displayed by clicking the Display button. The file cookies.js in the tools folder on the companion CD includes more sophisticated tools for cookie manipulation that can be easily added to any Web page.


HTML Applications

HTML Applications (HTAs) offer a cool new technology supported in Internet Explorer 5 on 32-bit Windows platforms only. An HTA is a Web page or set of pages that appear and behave more like a traditional application than like a Web page. The most basic type of HTA can be created simply by changing the filename extension of a traditional Web page from HTM or HTML to HTA. Double-clicking on such a file will cause it to open in a window that looks like a standard application, without the toolbar and navigation buttons found in Internet Explorer.

A more advanced way of creating HTAs is to use the <HTA:APPLICATION> tag inside the head of an HTA file. This approach allows a great deal of control over the appearance of the application window. The following bit of code demonstrates the use of the <HTA:APPLICATION> tag, along with some of the properties that can be used to modify the window.

<HTA:APPLICATION ID="oHTA"
  APPLICATIONNAME="DemoApp"
  BORDER="thick"
  CAPTION="yes"
  SHOWINTASKBAR="yes"
  SYSMENU="no"
  WINDOWSTATE="normal">

Table 22-2 gives a more in-depth view of some of the special properties that can be used in HTA tags.

Table 22-2 Special Properties Used in HTA Files

Name | Description
applicationName | Sets the name of the HTA. This name is specific to the HTA and makes it possible to determine whether the HTA is running, regardless of the URL used to launch it.
border | Sets the type of border to use. It can be thick (the default), thin, none, or dialog.
borderStyle | Sets the appearance of the border. It can be normal (the default), complex, raised, static, and sunken.
caption | Sets whether a title bar is displayed. Default value is yes.
commandLine | Read-only property that contains the path necessary to launch the HTA from the command prompt.
icon | A URL for an icon to use for the HTA. The icon should be a standard 32 by 32 pixel ICO file.
maximizeButton | Sets whether a maximize button is displayed. Default value is yes.
minimizeButton | Sets whether a minimize button is displayed. Default value is yes.
showInTaskbar | Sets whether the HTA is displayed in the Windows "taskbar" and in the ALT-TAB list. Default value is yes.
singleInstance | Sets whether multiple copies of the application can be run simultaneously. Default value is no.
sysMenu | Sets whether a system menu (the menu that appears when the title bar is right clicked) is enabled. Default value is yes.
version | Sets a version number for the application.
windowState | Sets the initial size of the HTA window. It can be normal, minimize, or maximize.

DemoApp.hta, shown below, is a sample HTA that is illustrated in Figure 22-7. (DemoApp.hta is included in the chap22 folder on the companion CD.)

<HTML>
<HEAD>
<TITLE>DemoApp</TITLE>
<HTA:APPLICATION ID="oHTA"
  APPLICATIONNAME="DemoApp"
  BORDER="thick"
  CAPTION="yes"
  SHOWINTASKBAR="yes"
  MAXIMIZEBUTTON="yes"
  MINIMIZEBUTTON="yes"
  WINDOWSTATE="normal">
</HEAD>
<BODY>
This is a basic HTML application.
</BODY>
</HTML>

Figure 22-7. A very basic HTML Application.

HTA Security

HTAs have different security restrictions than conventional Web pages. When an HTA is first downloaded, the user is asked whether it is to be trusted. If so, the user will not be asked to approve any other functionality of the HTA. This procedure is analogous to a traditional program, in which once a user has installed an application the application is given full access to the system's resources.

When an HTA has been loaded and approved, it is given access to many functions that are normally restricted. For example, HTA files have read/write access to the file system and the registry of the client's machine. HTAs can also use Internet Explorer command identifiers to do everything from changing the justification of a block of text to using the built-in Find command to locate and highlight text. Learn more about command identifiers from the SBN Workshop. On the companion CD see DHTML, HTML, & CSS; DHTML References; Command Identifiers. If your HTA contains FRAMEs or IFRAMEs that you do not control and that are not secure (for example, one frame might be intended to browse the Internet), you should force that frame to be bound by the standard security restrictions. You can accomplish this by setting the TRUSTED attribute of that FRAME or IFRAME to no—for example, <IFRAME SRC="somewhereElse.htm" TRUSTED="no">.


Creating Channels

Active Channels, based on Microsoft's Channel Definition Format (CDF), are one implementation of "push" technology. CDF can be a powerful tool for packaging and delivering content. Channels can be used to give access to the Windows desktop Channel Bar (shown in Figure 22-8) and the Channels folder in Internet Explorer, scheduled updates, the channel screen saver, software distribution channel, active desktop items, and much more. Users can also "pull" content from various content providers according to a schedule they create.

Figure 22-8. The Windows Channel bar.

An Active Channel is simply a Web site that is described using CDF, the Channel Definition Format. Like an HTML file, a CDF file is structured text made up of various elements, each enclosed within opening and closing tags. For an HTML file, the opening and closing tags are <HTML> and </HTML>. For a CDF file, the tags are—you guessed it—<CHANNEL> and </CHANNEL>.

Code Listing 22-7 shows the structure of a basic CDF file. To experiment with this example, you must copy the entire \chap22\cdftest folder from the companion CD to drive C on your computer. Then double-click lst22-7.cdf from c:\cdftest to try the channel. This will open the page and add it to your favorites, under Channels. The secondary pages of the channel can be accessed by clicking on this channel in your favorites.

Code Listing 22-7.

<?xml version="1.0"?>

<CHANNEL HREF="FILE://c:\cdftest\main.htm">
  <TITLE>Dynamic HTML in Action Test Channel</TITLE>
  <LOGO HREF="FILE://c:\cdftest\cdftest.gif" STYLE="image" />
  <LOGO HREF="FILE://c:\cdftest\cdftest.ico" STYLE="icon" />

  <ITEM HREF="FILE://c:\cdftest\page1\page1.htm">
    <TITLE>Channel test page 1</TITLE>
    <ABSTRACT>Page 1 of our channel test</ABSTRACT>
  </ITEM>

  <ITEM HREF="FILE://c:\cdftest\page2\page2.htm">
    <TITLE>Channel test page 2</TITLE>
    <ABSTRACT>Page 2 of our channel test</ABSTRACT>
  </ITEM>

</CHANNEL>

Click to view at full size.

Figure 22-9.The channel logo is displayed in the Internet Explorer Channels Folder.

NOTE
The HREF attribute in a <CHANNEL> tag and all other HREF attributes in a CDF file require absolute paths or complete URLs—for example, HREF="http://www.domain.com/channel/myChannel.htm". Relative paths such as /channel/myChannel.htm do not work in a CDF file. (In Code Listing 22-7, for instance, we had to use the absolute path c:\cdftest\.) Most often, these attributes refer to actual Internet sites.

You can learn more about channels (including technologies like Offline Browsing and the CDF Generator) from the Site Builder Network Workshop. On the companion CD see Workshop (References); Content & Component Delivery; Channel Definition Format (CDF).


Working with a Ratings System

Many people, especially parents, are concerned about the type of content available to minors on the Internet. The Internet is basically an open system of exchanging information without any built-in safeguards to control the types of content that can be downloaded to a browser. To help deal with this issue of safeguards, the World Wide Web Consortium (W3C) chartered the Platform for Internet Content Selection (PICS) group. According to the W3C, "PICS is an infrastructure for associating labels (metadata) with Internet content. It was originally designed to help parents and teachers control what children access on the Internet, but it also facilitates other uses for labels, including code signing and privacy." (For additional information about the PICS recommendations, visit the W3C PICS Web site at www.w3.org/PICS.)

The PICS recommendations consist of two specifications, one for creating a ratings system and one for creating rating labels. The first specification allows the establishment of a ratings system with multiple categories. This is in contrast to the Motion Picture Association of America (MPAA) ratings system, which has only one category containing the five values G, PG, PG-13, R, and NC-17. The PICS specification does not define a ratings system, but it provides a language for defining such a system.

The actual rating information comes in the form of a rating label. The label can appear as part of the header in an HTML document, on a separate Web site, or just about anywhere the browser has been told to look for the label. The rating line is a combination of category and value pairs that reflect the nature of content found on the page, as the final line of the <META> tag in the following code demonstrates.

<HEAD>
<META http-equiv="PICS-Label" content=`
  (PICS-1.1 "http://www.rsac.org/ratingsv01.html"
  l gen false comment "RSACi North America Server" for
  "http://www.myawesomelycoolwebsite.com" on "1998.11.07T17:38-0800"
  r (n 0 s 0 v 1 l 2))'>
</HEAD>

The PICS approach works by matching the label to its associated ratings system, and there are several ratings systems available. For example, the Recreational Software Advisory Council has the RSACi ratings system—supported in Internet Explorer and MicroSystem's Cyber Patrol Software—that provides five levels of four different categories, including violence, nudity, sex, and language (abbreviated to their first letters in the rating code above). SurfWatch has created a different system used by other products, such as Digital's AltaVista Web search engine.

Figure 22-10 shows the ratings of one system—Internet Explorer Content Advisor—that parents can use to set access levels on a home computer. If children (or anyone else using the computer) try to enter an area that contains a prohibited rating, their access to that site is restricted or denied.

Click to view at full size.

Figure 22-10. The Internet Explorer Content Advisor allows users to restrict access to objectionable content.

Of course, ratings systems work only if content providers use them. For more information about having content rated through the RSACi or SurfWatch systems, visit their Web sites at www.rsac.org/homepage.asp and www1.surfwatch.com/.

This chapter covered a variety of interesting technologies available to creators of Web pages. Some of them work with a number of browsers, while others are supported only in the latest versions of Internet Explorer. The next chapter will explore techniques for creating cross browser Web pages and Web pages that degrade gracefully when they contain browser-specific technology.


Chapter 23 -- Cross Browser, Cross Platform Web Pages

 Chapter 23

Cross Browser, Cross Platform Web Pages

The Web is a dynamic place. New versions of browsers (also known as clients or user agents) come out fairly often, and they usually include features that are not supported in other browsers or in earlier versions of the same browser. Some of these features do not work on every operating system (also known as an OS or a platform). This is because a feature might take advantage of built-in capabilities offered by one particular OS, or it might not be cost-effective in time, money, and effort to program for multiple platforms. In some cases, browsers are designed for special purposes and intentionally do not support features commonly supported by other browsers.

This chapter covers some general techniques for making your Web site accessible to multiple browsers. We will first cover some of the major differences among browsers; then we will examine some ways to make content more compatible across browsers; and finally we will explore some common problem areas in cross browser functionality and their solutions.


General Issues

In this section, we describe some of the many types of clients currently available on the Web, and then we discuss ways in which they differ.

There Are Many Different Browsers

Here is a selection of clients that commonly access Web pages:

  • Full-blown modern browsers such as Microsoft Internet Explorer 5 and Netscape Navigator.

  • Earlier versions of Internet Explorer and Netscape Navigator, which might not support any number of features, including frames, Cascading Style Sheets (CSS), and scripting.

  • Browsers that run on platforms other than Microsoft Windows. (Both Netscape Navigator and Microsoft Internet Explorer support more features on Windows than they do on Macintosh or Unix.)

  • Text-only browsers like Lynx and browsers designed for people who are blind.

  • Browsers intended for special purposes, such as Opera, which trades reduced feature support for increased speed.

  • Web crawlers, which index a site for a search engine or copy the contents of a site.

These clients are often profoundly different from one another.

Feature Support

As the Web has developed, so have Web browsers. New browser standards and proprietary features continue to be proposed and incorporated that are supported only in some clients. Often a standard or a feature is only partially supported, or it might have bugs in the way it is implemented by certain browsers. Additionally, a standard might have acknowledged problems that are intentionally not supported. Very few aspects of Web technology are supported identically in all browsers. Table 23-1 discusses support of a few widespread features in the most common browsers—Internet Explorer and Navigator.

Table 23-1 Cross Browser Support for Common Features

Feature | Notes
Frames | Best supported in version 3+ browsers.
HTML 3.2 | Best supported in version 3+ browsers, although version 2 browsers provide fair support. Defines support for tables and many other common HTML tools.
HTML 4.0 | Fair support in Internet Explorer 4, less in Navigator 4. Both browsers support this standard better with each new version. HTML 4.0 defines standards for frames, new tags, and new attributes, such as TITLE, which allows for pop-up text over almost any element and is supported in Internet Explorer but not currently in Navigator.
CSS | Support introduced in Internet Explorer 3, followed by Navigator 4. Internet Explorer versions 4 and later currently provide the most support. Differences in support among browsers (especially with Internet Explorer 3) sometimes cause problems. Opera 3.5 and later also provide good support. Indications are that Navigator 5 will have much improved CSS support.
JavaScript | First supported in Netscape Navigator 2, and then in Internet Explorer 3. Many subsequent changes make for some challenges with cross browser script. The introduction of ECMA-262 support in Internet Explorer 4.0 and Navigator 4.06 is helping to smooth out the bumps.
Java | Unpredictable prior to version 3 browsers. Java has improved as browsers have evolved.
Object Model | Variable support in all browsers. Some aspects of the Object Model have been around since the beginning of browsing. Version 3 browsers had much better support than earlier versions. Version 4 of Internet Explorer greatly expanded the Object Model to one that allowed accessing and changing almost all elements on a page. The W3C DOM specification should help drive the standardization of an Object Model among browsers. Tools like Scott Isaac's DHTMLLib (explained later in this chapter) can help make these differences in support easier to deal with.
ActiveX Controls | Supported in Internet Explorer 3 and later, with minor advances with each new version. The ScriptActive plug-in from NCompass Labs can add a level of ActiveX support to Netscape Navigator.
Forms | Well-supported in version 3+ browsers. Unfortunately, they are represented differently in the Object Models of each browser. Learn more about cross browser forms later in this chapter.

As you can see, there is great variation in support of various standards and features. Programming for the Web is always a tradeoff between using neat new features and providing support for the widest possible audience.

Which Browsers and Platforms Should You Support?

A recent analysis of the usage logs of a particular high-traffic Web site revealed that more than 200 different browser clients had accessed it. These clients ranged from version 2 of both Netscape Navigator and Internet Explorer to unreleased beta versions of each of these browsers. They included other browsers, such as Opera, Mosaic, and Lynx, as well as a number of different Web crawlers. These diverse clients resided on operating systems ranging from Windows 3.1 to various flavors of Unix and different versions of the Macintosh operating system. These browsers have obvious and subtle differences among them.

However, despite this variety of Web clients, more than 96 percent of the traffic on the Web site described above came from people using the two most recent full versions of either Internet Explorer or Netscape Navigator. Keep in mind that the percentages of different clients that access a site vary tremendously from Web site to Web site. The users of msdn.microsoft.com are more likely to use Internet Explorer than are visitors to developer.netscape.com. Developers for the Apple Web site at apple.com are probably more concerned with making their site work on Macintosh machines than those creating an intranet for a PC-only company.

Ultimately, Web site developers need to decide what types of clients they will support based on the type of user they expect to visit their sites. All modern Web server applications can track the types of clients that access them. If possible, you should obtain a report (typically an analysis of the log files from the server) that breaks down the clients that visit your site. Luckily, there are many techniques for creating cross browser content.


Creating Cross Browser Content

Cross browser content is a loose concept. It does not mean that a particular Web page will work for every browser. Cross browser content almost always boils down to a page working well for a fairly wide audience using a variety of browsers. There are several ways to make content that works for the widest possible audience. These include using the following.

  • Commonly supported features

  • "Gracefully degrading" features

  • Browser detection, and then using only features supported by the current browser

We'll take a look at each of these techniques next.

Using Commonly Supported Features

Technically, the only way to create complete cross browser content is to use only features supported by all browsers. Unfortunately, this option won't fly with most artists or designers, as it doesn't allow for such basic features as using images or changing fonts. However, it is possible to reach upwards of 99.9 percent of your audience if you stick with the basics. Even if you plan on using more advanced features, it is often possible to find some crossover in the support of more advanced features among different browsers.

Sticking with the Basics

Capabilities supported by virtually all clients include GIF images (JPG images are almost as widely supported), hyperlinks with the <A> tag, and very basic HTML, like <P>, <B>, <I>, <TITLE>, <OL>, <LI>, etc. You can find out more about early versions of the HTML standard from the W3C Web site at www.w3.org/MarkUp/.

Almost as large an audience can be reached by conforming to the HTML 3.2 standards, which are well supported in version 3+ browsers. Following these standards gives support for almost all of the commonly used tags. The HTML 3.2 specification is a fairly short document and is recommended reading. It can be found at the W3C Web site specified above.

If you just write a Web page, it is difficult to tell if you have conformed to a particular specification. To meet this need, a class of programs called validators has been created. A validator will read through a document and check it against a set of rules to make sure it conforms. Many good validators are available that can check documents against the HTML 3.2 standard. The HomeSite Web page editor (available from Allaire at www.allaire.com) includes a good validator that has been integrated into the editor itself. Being able to validate code while writing it is very valuable. The W3C provides a validation service at validator.w3.org. Additional validators include HTML Check (available from www.netmechanic.com) and Weblint (available from www.cre.canon.co.uk/~neilb/weblint/).

Varied Support

Some of the more advanced features are supported in different ways in different browsers. Prime examples of this are the forms and elements found in forms. For example, Internet Explorer allows <INPUT>, <TEXTAREA>, and <SELECT> tags to be used anywhere in a document, while Netscape Navigator requires that they be contained in a FORM element. Also, Internet Explorer supports the <BUTTON> tag, which is not supported in current versions of Navigator. Most Web crawlers do not support submitting data from forms at all. Scripting support also differs widely among different browsers and browser versions, as demonstrated in Code Listing 23-1. The results are displayed in Figure 23-1.

Code Listing 23-1.

<HTML>
<HEAD>
<TITLE>Listing 23-1</TITLE>
<SCRIPT LANGUAGE="JavaScript">
function getValIE4(){ alert(F1.S1.value) }
function getValMore(){
  alert(document.F1.S1.options[document.F1.S1.selectedIndex].value)
}
function getValMost(){
  oSelect=document.F1.S1
  // Iterate through all of the OPTIONS in the SELECT
  for (var i=0;i<oSelect.options.length;i++) {
    // If this one is selected, get its value
    if (oSelect.options[i].selected==true){sVal=oSelect.options[i].value}
  }
  alert(sVal)
}
</SCRIPT>
</HEAD>
<BODY>
<HR>
<FORM NAME="F1">
<SELECT NAME="S1">
  <OPTION VALUE="1st Item">First Item
  <OPTION VALUE="2nd Item">Second Item
  <OPTION VALUE="3rd Item">Third Item
</SELECT>
<P>Click a button to display an alert box with the item chosen above<P>
<INPUT TYPE="BUTTON" onclick="getValIE4()" VALUE="IE4+ only"><BR>
<INPUT TYPE="BUTTON" onclick="getValMore()" VALUE="NS3+ and IE4+"><BR>
<INPUT TYPE="BUTTON" onclick="getValMost()" VALUE="NS3+ and IE3+"><BR>
</FORM>
</BODY>
</HTML>

Click to view at full size.

Figure 23-1. Each of the buttons uses a different function to display the value of the selected item.

As you can see in Figure 23-1, this example displays a Select box and several buttons. Clicking a button will display an Alert dialog box that contains the value currently selected in the Select box. Notice that three different functions are used by the different buttons in Code Listing 23-1. These three functions demonstrate how support for scripting forms has changed as browsers have become more advanced.

getValIE4 The easiest to understand of these functions is getValIE4. This function uses the code F1.S1.value to refer to the value of the Select box named S1 in the form named F1. This function is intuitive and easy to use. Unfortunately, it is supported only in versions 4 and later of Internet Explorer. In other browsers and in earlier versions of Internet Explorer, this function results in an error.

getValMore The second function, getValMore, is supported in more browsers, namely Netscape Navigator 4 and later and Internet Explorer 4 and later. This function does several things differently than getValIE4. First of all, Navigator requires that the document object be used when referring to a form. Therefore, document.F1 is used to refer to our form rather than simply F1. The options collection is present on all SELECT elements and simply contains a list of all of the <OPTION> tags that the SELECT element contains. The selectedIndex property of the SELECT element contains the (zero-based) number of the selected OPTION. Thus, document.F1.S1.selectedIndex gets the number of the selected item. We can use it in combination with the options collection to get the value of the selected item in the options collection, as demonstrated in the following code.

document.F1.S1.options[document.F1.S1.selectedIndex].value

Unfortunately, Internet Explorer 3 does not support the value attribute when an option is referred to in this way, and so this function will result in an error.

getValMost Finally, the third function, getValMost, uses only features that are supported in versions 3 and later of both browsers. Both browsers support a property on OPTION elements named selected, which has a value of true when the item is selected and false when the item is not. The getValMost function loops through all of the members of the options collection and tests whether the selected property has a value of true. If it does, the value of that option is recorded in the sVal variable. After checking all the options, the value of the sVal variable is displayed in an Alert dialog. All of these features are supported in our target browsers (versions 3 and later of Internet Explorer and Netscape Navigator), and this function is successful, though cumbersome.

This example illustrates the importance of testing programs in all target browsers. It also illustrates the importance of restricting the number of browsers you support so that you can get to know their features and limitations.

NOTE
In Code Listing 23-1, if we were using a SELECT element that allowed multiple options to be selected, we would want to modify the functions slightly so that they displayed all the selected items. For example, in the third function we would want to append each selected value to sVal rather than replacing the current sVal.

Gracefully Degrading Pages

Pages containing advanced features that can still be used by browsers that do not support these features can be described as gracefully degrading. For example, CSS technology degrades fairly gracefully; a page that uses standard HTML 3.2 with the addition of CSS will display the styles in Navigator 4, but will simply look as though no CSS had been specified when viewed in Navigator 3. Behaviors are another gracefully degrading technology. Browsers that do not support behaviors ignore behavior code, while browsers that do support behaviors, such as Internet Explorer 5, display them.

The standard rule when using any feature that is not supported in all of your target browsers is to make sure that your site does not depend on that feature for key functionality. For example, if you want to target users of text-only browsers, you should not rely on a Macromedia Flash file (graphic only) for navigation. You should not use a Dynamic HTML expanding menu for navigation without putting careful thought into how it will behave in browsers that do not support DHTML. As a general rule, you should not use any functionality unless it is supported by all of your target browsers or it provides a substantial benefit.

Typically, features that do not degrade well are fairly easy to identify. Simply opening the file in the oldest versions of the browsers you want to support will usually show you any problems.

You can also take advantage of the fact that some features are not supported in some browsers. For example, the <COMMENT> tag (part of the HTML 4.0 specification) can be used like <!-- ... --> to prevent text from displaying. However, it is not supported in Netscape Navigator through version 4 or Internet Explorer prior to version 3. Thus, the following code will cause a warning to appear only in those browsers that do not support this tag.

<COMMENT>
This page is designed for a browser that supports HTML 4.0.
Please upgrade if possible.
</COMMENT>

Browser Detection

Browser detection (also known as browser sniffing) is simply proactively determining which browser a client is using. A page can contain code that determines the browser being used and changes the content of the page so that only appropriate features are used.

There are two major ways to perform browser sniffs. You can get information about the browser directly from the navigator object. In this way, for example, you could tell precisely which fractional version of Netscape 4 (4.05, 4.06, and so on) is being used. Alternatively, you can test for functionality specific to the target browser. For example, if the client's browser has a layers object, it must be Netscape 4 or later.

Using the navigator Object

The navigator object contains a lot of useful information about the browser being used. Code Listing 23-2 demonstrates some of the properties of the navigator object. Figure 23-2 shows this page displayed in Internet Explorer 5, while Figure 23-3 shows the results in Netscape Navigator 4.08.

Code Listing 23-2.

<HTML>
<HEAD>
<TITLE>Listing 23-2</TITLE>
</HEAD>
<BODY>
<H2>Information about the <I>navigator</I> object in this browser.</H2>
<SCRIPT LANGUAGE="JavaScript">
document.write("<BR><B>userAgent</B>="+navigator.userAgent)
document.write("<BR><B>appMinorVersion</B>="+navigator.appMinorVersion)
document.write("<BR><B>appVersion</B>="+navigator.appVersion)
document.write("<BR><B>appName</B>="+navigator.appName)
document.write("<BR><B>appCodeName</B>="+navigator.appCodeName)
document.write("<BR><B>browserLanguage</B>="+navigator.browserLanguage)
document.write("<BR><B>cookieEnabled</B>="+navigator.cookieEnabled)
document.write("<BR><B>cpuClass</B>="+navigator.cpuClass)
document.write("<BR><B>onLine</B>="+navigator.onLine)
document.write("<BR><B>platform</B>="+navigator.platform)
document.write("<BR><B>systemLanguage</B>="+navigator.systemLanguage)
document.write("<BR><B>userLanguage</B>="+navigator.userLanguage)
</SCRIPT>
</BODY>
</HTML>

Click to view at full size.

Figure 23-2. Some of the properties of the navigator object in Internet Explorer 5.

Click to view at full size.

Figure 23-3. The same page in Netscape Navigator 4.08.

The navigator object has a number of useful properties. Each contains some information about the browser being used. The most useful properties are appVersion and userAgent, which give information about the browser, the version, and the operating system all in one place. Table 23-2 shows the values for the appVersion property in a variety of situations.

The number at the beginning of the appVersion property specifies to which version of Netscape Navigator the browser is designed to be similar. The information in parentheses usually describes the user's browser (if not Navigator) and operating system. The latest version of Navigator available when Internet Explorer 5 was released was version 4; therefore Internet Explorer 5 reports an appVersion of 4.0. All versions of Internet Explorer include the characters MSIE in the appVersion property, followed by the version. The userAgent property contains similar information. Script can examine the contents of this property to determine exactly which browser is running, and then act accordingly. For example, Code Listing 23-3 tests the browser and version and writes a style sheet based on the browser being used. Figure 23-4 displays the results.

Code Listing 23-3.

<HTML>
<HEAD>
<TITLE>Listing 23-3</TITLE>
<SCRIPT LANGUAGE="JavaScript">
av=navigator.appVersion
// Check if IE and if so, check version
iMSIE=parseInt(av.indexOf("MSIE"))
if (iMSIE>=1){
  // Get major version and write appropriate style
  iVer=parseInt(av.charAt(iMSIE+5))
  if (iVer==3){ sStyle = "color:blue;font:italic" }
  if (iVer==4){ sStyle = "color:blue;" }
  if (iVer>=5){ sStyle = "color:blue;font:bold" }
  document.write("<STYLE>body{"+ sStyle +"}</STYLE>")
}
// If not IE, check if it's Netscape, if so, check version
else {
  if (navigator.appName=="Netscape"){
    if (parseInt(av) >= 4){
      document.write("<STYLE>body{color:red;}</STYLE>")}
  }
}
</SCRIPT>
</HEAD>
<BODY>
This page senses the browser and uses a different style sheet for each.
<HR>
The page will be blue in Internet Explorer. In version 3 the text will
be italicized, in version 4 it will be normal, and in version 5 and later
it will be bold.
<HR>
In version 4 and later of Netscape Navigator the text is red. Prior
versions do not use style sheets and display the page as standard text.
</BODY>
</HTML>

Click to view at full size.

Figure 23-4. This page writes a different style sheet in each browser.

Table 23-2 appVersion Property Values

Browser | Operating System | appVersion String
Internet Explorer 3.02 | Windows 95 | 2.0 (compatible; MSIE 3.02; Windows 95)
Internet Explorer 4.01 | Windows 95 | 4.0 (compatible; MSIE 4.01; Windows 95)
Internet Explorer 4.01 | Windows NT | 4.0 (compatible; MSIE 4.01; Windows NT)
Internet Explorer 5 Beta 2 | Windows 98 | 4.0 (compatible; MSIE 5.0b2; Windows 98)
Internet Explorer 5 | Windows 98 | 4.0 (compatible; MSIE 5.0; Windows 98)
Netscape Navigator Gold | Macintosh System 7.5 | 3.02Gold (Macintosh; I; 68K)
Netscape Navigator 3.04 | Windows 95 | 3.04 (Win95; I)
Netscape Navigator 3.04 | Windows 98 | 3.04 (Win95; I)
Netscape Navigator 4.08 | Windows 95 | 4.08 [en] (Win95; I; Nav)
Netscape Navigator 4.08 | Windows 98 | 4.08 [en] (Win98; I; Nav)
Netscape Navigator 4.08 | Windows NT | 4.08 [en] (WinNT; I; Nav)

First the indexOf method is used to determine where in the appVersion property the string MSIE is found. If it appears at all, it means that the browser is some version of Internet Explorer. The code then retrieves the major browser version, which is the number that appears after the text MSIE. Note that the code is "forward-compatible"; if the version number is greater than 5, it is treated as 5.

If the string MSIE is not found, indexOf("MSIE") will return −1 and the code will enter the else block. At this point, we check to see whether the browser is Netscape Navigator by checking the appName property of the navigator object. If so, we use parseInt (see Chapter 8 for more information) to convert the appVersion property to a major version number, which we then test. If the browser is not Internet Explorer or Netscape Navigator, the if and else blocks will not be run and no style sheet will be written.

To make sniffing browsers easier, the following script file can be found on the companion CD as chap23\ sniffer.js. The sniffer.js file is a generic browser sniffer that uses Boolean variables to hold information about the browser being used. You can either copy the text of the file for your own Web pages or include it as a .js file (covered in Chapter 6).

<SCRIPT LANGUAGE="JavaScript">

<!--
// This script checks browser being used and its version
var bIE=false, bIE5=false, bIE5=false, bIE4=false, bIE3=false, bIE2=false
var bNS=false, bNS4=false, bNS3=false, bNS2=false

av=navigator.appVersion;
// Check if Internet Explorer and if so, check version
iMSIE=parseInt( av.indexOf("MSIE") )
if ( iMSIE >= 1 ){
  bIE = true;
  if ( parseInt( av.charAt(iMSIE + 5) ) == 3 ){ bIE3=true }
  else if ( parseInt( av.charAt(iMSIE + 5) ) == 4 ){ bIE4 = true }
  else if ( parseInt( av.charAt(iMSIE + 5) ) >= 5 ){ bIE5 = true }
}
// If not Internet Explorer, check if it's Netscape, if so, check version
else {
  if ( navigator.appName == "Netscape" ){
    bNS = true;
    if (parseInt(av) >= 4){ bNS4 = true }
    else if ( parseInt(av) >= 3 ){ bNS3 = true }
    else { bNS2 = true }
  }
}
//-->
</SCRIPT>

There are more full-featured sniffers available on the Web that provide more detailed information than our basic version, including fractional versions and operating system information. Good references can be found at developer.netscape.com/docs/examples/javascript/browser_type.html and on the SBN Workshop Web site. On the companion CD, go to Workshop (References); Web Content Management; Sniffing for Browser, VM, & OS. To get to the online version, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm, or open the file named MSDN_OL.htm on the companion CD, and choose Browser Detection.

Detecting Browser Functionality

It is frequently useful to test the capabilities of a browser rather than the exact browser version. After all, the browser version does not matter as much as whether the browser can perform a certain function. For example, the only browsers that currently support the document.all collection are Internet Explorer versions 4 and later. Some useful objects that can be tested include

document.all | Internet Explorer 4 and later
window.Event | Netscape Navigator 4 and later (The Internet Explorer version is window.event.)
document.images | Internet Explorer 4 and later and Netscape Navigator 3 and later
document.layers | Netscape Navigator 4 and later

Code Listing 23-4 sets a variable named bImg to true if the browser has an images collection. When a user moves the mouse over the image on a page, an event handler tests whether bImg is true; if so, it changes the image. In this case, we do not care what the browser is, as long as it supports the images collection. The file IENSSwap.htm in the crossplat folder on the CD contains an expanded version of this file that can be used for generic image-swapping tasks.

Code Listing 23-4.

<HTML>
<HEAD>
<TITLE>Listing 23-4</TITLE>
<SCRIPT LANGUAGE="JavaScript">
if (document.images) { var bImg=true }
</SCRIPT>
</HEAD>
<BODY>
<BODY>
<A HREF="http://www.microsoft.com"
  onmouseover="if (bImg){document[`Img1'].src=`2.gif'}"
  onmouseout="if (bImg){document[`Img1'].src=`1.gif'}"
><IMG NAME="Img1" SRC="1.gif" BORDER="0"></A>
</BODY>
</HTML>

Conditional Comments

Conditional comments are a new feature in Internet Explorer 5. This feature is essentially a new type of comment that lets you selectively comment out content based on whether Internet Explorer 5 is running. Conditional comments are inherent in the browser and do not require that a script engine load, meaning that the page as a whole will load faster. They are demonstrated in the following example:

<!--[if IE 5]>
This text displays in Internet Explorer 5. Other browsers do not
display it because it is in a traditional comment tag.
<![endif]-->
<![if ! IE 5]>
This text is not in a traditional comment tag and so is displayed,
except in Internet Explorer 5.
<![endif]>

Note that the first block of code is in a traditional comment tag (shown in bold).

This block will not display in most browsers. Internet Explorer 5 looks inside the comment tag and sees the [if IE 5] test. It then displays the content because it is Internet Explorer 5. The subsequent block of text is not in a traditional comment tag, and so it does display in normal browsers. Internet Explorer 5 sees the test [if ! IE 5], fails it, and so does not display the text.

As of this writing, conditional comments are at a very basic stage of development. They let you determine only whether Internet Explorer 5 is the active browser. This feature might become more powerful later.

Conditional Compilation

Conditional compilation is a technology new to Internet Explorer 4. It allows easy testing of a number of environmental properties, including the client operating system and the type of CPU. Table 23-3 lists the variables it supports.

Table 23-3 Variables Supported by Conditional Compilation

Variable | Description
@_win32 | true if using a Win32-based operating system (Windows 95 or later, Windows NT, or Windows 2000 or later)
@_win16 | true if using a Win16-based operating system (Windows 3.x)
@_mac | true if using an Apple Macintosh operating system
@_x86 | true if using an Intel compatible processor (486, Pentium, Pentium II, and so on)
@_alpha | true if using an Alpha processor
@_mc680x0 | true if using a Motorola 680x0 processor (found in older Macintosh compatibles)
@_PowerPC | true if using a PowerPC processor (found in newer Macintosh compatibles)
@_jscript | Always returns true
@_jscript_build | Holds the JScript scripting engine build number
@_jscript_version | Holds the complete version number of the JScript engine

Conditional compilation is first turned on with the @cc_on statement. Once it is active, the conditional statements @if, @elif, @else, and @end can be used together to test the state of the variables listed above. The @set statement can be used create your own variables, for example @set @var1 = 12345. Placing the conditional compilation code in JavaScript comments (these begin with /* and end with */) ensures that it does not cause problems in browsers that do not support it. Code Listing 23-5 demonstrates a basic use of conditional compilation.

Code Listing 23-5.

<HTML>
<HEAD>
<TITLE>Listing 23-5</TITLE>
<SCRIPT LANGUAGE="JavaScript">
/*@cc_on @*/
/*@if (@_win16)
    alert("You should consider upgrading your operating system.");
  @elif (@_mac)
    alert("You are using a Macintosh.");
  @elif (@_win32)
    alert("You are using a Win32 based operating system.");
  @else
@*/
    alert("Not using Internet Explorer on a Macintosh or on Windows.");
/*@end @*/
</SCRIPT>
</HEAD>
</HTML>

Client Capabilities

Client capabilities are a default behavior included with Internet Explorer 5 that can be used to give extensive information about the user's system. Some of the available information includes the height, width, and color depth of the user's display; the type of processor, operating system, and net connection being used; whether cookies are enabled; whether Java is available, as well as the version of Java installed; and the language being used. This behavior also provides a number of methods. These include mechanisms for component management, such as checking whether a component is installed, installing a component, comparing version numbers, and several more. There are many ways the client capabilities behavior can be implemented. See the SBN Workshop Web site or the CD that accompanies this book. On the CD, choose DHTML, HTML & CSS; DHTML Behaviors; Default Behaviors Reference, and click the Behaviors bullet point in the right frame. To get to the online version, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm, or open the file named MSDN_OL.htm on the companion CD, and choose Client Capabilities. Code Listing 23-6 demonstrates retrieving the values of the client capabilities properties. Figure 23-5 displays the results.

Code Listing 23-6.

<HTML>
<HEAD>
<TITLE>Listing 23-6</TITLE>
</HEAD>
<BODY>
<IE:clientCaps ID="oClientCaps" />
Client Capabilities properties on this system.
<PRE>
<SCRIPT LANGUAGE="JavaScript">
oClientCaps.style.behavior = "url(#default#clientCaps)";

document.writeln("width          = "+oClientCaps.width)
document.writeln("height         = "+oClientCaps.height)
document.writeln("availHeight    = "+oClientCaps.availHeight)
document.writeln("availWidth     = "+oClientCaps.availWidth)
document.writeln("bufferDepth    = "+oClientCaps.bufferDepth)
document.writeln("colorDepth     = "+oClientCaps.colorDepth)
document.writeln("connectionType = "+oClientCaps.connectionType)
document.writeln("platform       = "+oClientCaps.platform)
document.writeln("cpuClass       = "+oClientCaps.cpuClass)
document.writeln("cookieEnabled  = "+oClientCaps.cookieEnabled)
document.writeln("javaEnabled    = "+oClientCaps.javaEnabled)
document.writeln("systemLanguage = "+oClientCaps.systemLanguage)
document.writeln("userLanguage   = "+oClientCaps.userLanguage)
</SCRIPT>
</PRE>
</BODY>
</HTML>

Click to view at full size.

Figure 23-5. This page displays a number of different system settings.


Common Problem Areas

There are literally thousands of areas in which browser differences can (and will) trip up Web developers. This section tries to address some of the most common problems.

BODY and FRAMESET on the Same Page

The HTML 4.0 specification limits a document to having a FRAMESET or a BODY element, but not both (unless the BODY element is contained in a NOFRAMES element for browsers that do not support frames). Internet Explorer supported both in the same document prior to version 4, at which point this support was removed. If both appear in the same document, the second is ignored. You can also accidentally imply a BODY element by using elements that are only valid within a BODY element (such as IMG and TABLE).

Cascading Style Sheets Differences

Unfortunately, the implementation of Cascading Style Sheets (CSS) varies widely from browser to browser. Internet Explorer 3 is particularly problematic. This browser was released prior to the final release of the CSS Level 1 specification. As such, it unavoidably implemented certain features in a different way than was decided upon in the ultimate release of the specification. For example, the em unit of measurement is not supported and might be treated as px. Also, setting a percentage font size for an element changes it based on its default size, rather than the size of its parent. Another example is that Netscape Navigator 4, Internet Explorer 3, and Internet Explorer 4 all implement CSS inheritance in different ways. Support for shorthand attributes is spotty in Internet Explorer 3 and Navigator 4, and some features are simply implemented differently.

Frequently, the best solution for this problem is to use separate style sheets for each browser, as demonstrated earlier in this chapter in the section on browser detection. A variant on this technique is to use a single style sheet in all browsers to handle the core CSS attributes (text color, size, and so on) that migrate well among browsers, and then use a second, specific style sheet for each browser. Another technique (which is most valuable if you are targeting only different versions of Internet Explorer) is to take advantage of the fact that Internet Explorer 3 does not support multiple style sheets or the DISABLED attribute, both of which are supported in Internet Explorer 4, as follows:

<!--Used in Internet Explorer 4 and later, not in version 3-->
<STYLE>
  span {color:red}
</STYLE>
<!--Used in Internet Explorer 3, but
       disabled in version 4 and later-->
<STYLE DISABLED>
  span {font-size:20pt}
</STYLE>

This technique is not as useful when targeting Navigator. Navigator 4 supports multiple style sheets, but not the DISABLED attribute. Thus, Navigator uses both of the style sheets, Internet Explorer 4 and later use only the first, and Internet Explorer 3 uses only the second.

Inconsistent Object Model

Object Model support varies substantially from browser to browser. For example, Netscape Navigator does not support event bubbling in the same way as Internet Explorer. Scott Isaacs, a Microsoft developer and author, has created a tool called DHTMLLib that is designed to overcome some of these differences by approximating an Internet Explorer Object Model inside Navigator. This tool is available from www.insidedhtml.com/writeOnce/writeOnce.asp.

Background Window Color

Internet Explorer versions 3 and earlier and all current versions of Netscape Navigator use gray as the default background color of the page, while Internet Explorer versions 4 and later use white. If you want to explicitly set the color of the page and are concerned about version 3 and earlier browsers, use the BGCOLOR attribute of the <BODY> tag, as follows.

<BODY BGCOLOR="white" TEXT="black">

When setting an explicit background color, it is important to also set a default text color to ensure that your background color will not conflict with the foreground text color. If you are only concerned with version 4 and later browsers, you can explicitly set the colors through CSS with the background-color and color CSS attributes on the BODY element.

Differences in Script Support

Scripting languages have evolved substantially in the past few years. Some new features are not supported in older browsers. One very useful technique is to do your primary development on the oldest supported browser. Since features tend to be forward compatible, your scripts are much more likely to work when used in a more recent browser than in an older one. Additionally, Internet Explorer 3 and later can be upgraded to more recent versions of the JScript engine. You might want to put links on your pages to the most recent script engines, available from msdn.microsoft.com/scripting, so that your users can upgrade.

Different Degrees of Flexibility in HTML Interpretation

It is common to find Web pages that do not strictly conform to HTML standards. For example, the following is invalid HTML.

<P>
<H1>Heading</H1>
</P>

According to the HTML specification, block-level elements such as H1 are not permitted inside a P element, thus the P element actually ends at the beginning of the H1 and the </P> is superfluous. When Netscape Navigator interprets the above code, styles placed on the BODY element might be lost after the closing </P>. Another common example is that Netscape Navigator 4 might not properly display a table that is missing the closing </TABLE> tag. The best way to avoid this sort of problem is to validate your HTML before you publish it to the Web.

These are just some of the problems you might run into when creating cross browser content for the Web. Luckily, there are many Web sites devoted to the art of Web development. Several highly recommended sites include webreview.com, webreference.com, developer.netscape.com, msdn.microsoft.com, microsoft.com/sitebuilder, and www.w3.org.


Chapter 24 -- Putting it all Together

 Chapter 24

Putting it all Together

In this book, we have covered a variety of techniques for Web programming. This chapter is intended to provide an example of how these different Web technologies can be used together in a sample Web site. The demo Web site includes browser sniffing, CSS, basic forms validation, and many more features. In addition, we will mention some techniques that can be used only over the World Wide Web, not on a CD.


The Features

The sample site provides general information about this book. It contains the following features:

  • General information about the book

  • Information about the authors

  • Links to useful resources

  • An electronic version of this book

  • Links to all the code listings

  • User-definable appearance (customization)

  • A DHTML expanding menu on the left of the screen (for supporting browsers)

  • Navigation through a drop-down list

  • Pages that automatically load themselves in the correct frameset

  • Support for Internet Explorer 3.02 and later and Netscape 3 and later.

    The sample site uses many specific coding techniques, including:

  • Use of frames, tables, forms, style sheets, the Object Model, and cookies

  • Cross-frame scripting

  • Links to external CSS and JS files

  • Browser detection

  • Dynamic content through document.write

  • Dynamic event handling, based on browser type

    Figure 24-1 shows the home page of our sample site, as viewed in Internet Explorer.

Click to view at full size.

Figure 24-1. The home page for our Web site.


The Files

Table 24-1 lists the different HTM files used to create the Web site. (It excludes files that this site is linked to, such as those in the SBN Workshop.) Table 24-2 lists the CSS and JS files used in the project, as well as their purposes and which files use them. Any reference to content pages in either table refers to the files main.htm, custom.htm, authors.htm, and links.htm.

Table 24-1 HTM Files Used to Create the Sample Web Site

File Description
default.htm

  • Creates the main frameset document

  • Reloads itself as the top frameset when loaded as part of a different frameset

  • Reads a cookie

  • Writes frames dynamically, based on a passed parameter (found after a hash mark in the URL)

  • Includes NOSCRIPT and NOFRAMES elements for early browsers

menu.htm

  • Creates left hand menu frame

  • Uses browser detection

  • Creates DHTML menu, custom event handlers, and custom styles and classes based on browser

  • Iterates through document.all

  • Loads itself in correct frameset

  • Creates main content frame

  • Uses a table and a form

  • Provides drop-down list navigation

custom.htm

  • Allows user to customize the look and feel of some pages

  • Uses forms

  • Uses browser detection provided by sniffer.js

  • Writes a cookie

authors.htm

  • Includes information about the authors
links.htm

  • Contains links to useful resources

Each of the content pages

  • Uses content.css

  • Uses legal.js to write copyright information

  • Uses frameit.js to load page in correct frameset

Table 24-2 CSS and JS Files Used to Create the Sample Web Site

File | Used by | Purpose
cookies.js | default.htm | Allows reading and writing cookies
custom.js | Content pages (non-external pages in right hand frame) | Handles style sheet customization
frameit.js | Content pages | Automatically loads content pages in correct frameset
legal.js | Content pages | Writes a copyright notice to the page
sniffer.js | As needed | Performs browser detection
menu.css | menu.htm | Sets basic formatting for the menu
content.css | Content pages | Sets basic formatting cascades with any custom formatting set through custom.htm

Now let's look at some of these pages in more depth.

default.htm

The default.htm page is the main frameset document for the site. Like most pages in the site, it begins with a number of linked JS scripts, which allow multiple pages to point to a single file that contains script. Linked JS scripts are supported in version 3.02 and later of Internet Explorer, as well as version 3 and later of Netscape Navigator. Support of this feature is the primary reason that we decided to target these browsers as the minimum requirement. This document can be found in the file named chap24\default.htm on the companion CD and is also shown here:

<HTML>
<HEAD>
<TITLE>Dynamic HTML in Action, 2nd Edition</TITLE>
<SCRIPT LANGUAGE="JavaScript" SRC="js/cookies.js"></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" SRC="js/sniffer.js"></SCRIPT>
<SCRIPT LANGUAGE="JavaScript">
//-----------------------------------------------------
// Make sure file is not hosted in a different frameset
if ( top.location.href != window.location.href )
  { top.location.href=window.location.href }

//-----------------------------------------------------
// Get any customization info about the user.
var sCookie = GetCookie("CstmStyle");
var sCstmStyle = ( ( (sCookie != null) && bVer4 ) ? sCookie : null)

//-----------------------------------------------------
// Construct the frameset. If passed a target content frame, load it.
// Otherwise, load main.htm

// Get content of URL after any #
var sPostHash=location.hash.substring(location.hash.indexOf(`#')+1);

// Break up normal HTML tags to prevent premature ending of the script
sFrmStart = ("<FRAM"+"ESET COLS=`200,*'><FRA" + "ME src=`menu.htm'>");
if (sPostHash=="") {sFrmMain="<FRA" + "ME src=`main.htm' NAME=`main'>"}
else {sFrmMain = ( "<FR" + "AME src=`" + sPostHash + "` NAME=`main'>")}
sFrmEnd = ("</FRA"+"MESET>");

document.write(sFrmStart + sFrmMain + sFrmEnd)
</SCRIPT>
<NOSCRIPT>
<FRAMESET COLS=`200,*'>
<FRAME src=`menu.htm'>
<FRAME src=`main.htm' NAME=`main'>
</FRAMESET>
</NOSCRIPT>
<NOFRAMES>
This Web site requires a frames-capable browser.
</NOFRAMES>
</HEAD>
</HTML>

The two linked JS files in default.htm are cookies.js and sniffer.js. We will discuss these scripts in detail a little later in the chapter. The first explicit script in default.htm is as follows:

//-----------------------------------------------------
// Make sure file is not hosted in a different frameset
if ( top.location.href != window.location.href )
  { top.location.href=window.location.href }

The first two lines of code are comments that describe the purpose of this block. Though not strictly necessary for the code to function, they make it far easier to read the code and understand its purpose. We can see from the comment that this text is supposed to ensure that default.htm is not being displayed as part of another frameset. Designers of sites who want to protect content often use this technique. For example, a news agency might wish to ensure that their news stories are not being presented in the frameset of another company's Web site.

Next comes the code that performs this action. If the URL of the top frame in the window (defined by top.location.href) does not match the URL of default.htm (the location of the current window, defined by window.location.href), the top window is explicitly set to point to default.htm. You can test this functionality by launching default2.htm in the chap24 folder on the companion CD: it attempts to load default.htm in a child frame, but it cannot.

NOTE
The name default.htm is common for files on the World Wide Web. Many Web servers are set up such that if a Web page of a particular name (such as default.htm, default.asp, or index.htm) exists in a specific directory, and a user goes to a URL that ends in that directory name (for example, www.w3.org/Style), the Web page is automatically displayed. The particular filenames can normally be configured in the server software.

The next block of code in default.htm reads any information stored in a cookie previously written by this site. The conditional operator ?: is used to assign the values returned by the cookie to the variable sCstmStyle if the cookie isn't empty and the user has a version 4 or later browser. Otherwise, sCstmStyle is set to null. Next, the frameset for the site is created. It is created dynamically out of a series of strings and then written to the screen with document.write. Though this process is somewhat complex, it allows us to do some nifty things. One of the features designed into the site is that content pages loaded outside of the default.htm frameset will load the correct frameset and point the content frame to the correct content file. When this happens, the exact URL that is loaded is default.htm followed by a hash mark (#) and the URL of the page that was incorrectly loaded.

The code that dynamically writes the frameset takes any value passed after the hash mark and uses it in the SRC attribute of a <FRAME>. If no such value is passed, the code simply points the SRC attribute to main.htm and the default frameset is created.

One other notable technique found in the creation of the frameset is that the text that makes up the <FRAME> and <FRAMESET> tags is split up into two distinct strings. The browser will notice some HTML tags in the middle of strings and will try to render them immediately, usually causing an Unterminated String Constant error in Internet Explorer and a lack of content in Netscape Navigator. The most problematic tags for this are <SCRIPT>, </SCRIPT>, <HEAD>, </HEAD>, <BODY>, </BODY>, <HTML> and </HTML>. This problem can be solved simply by breaking up the tag into two separate strings that are not read as a tag until the string is written to the screen. <FRAME> and <FRAMESET> are typically not as problematic as the above listed tags.

At the bottom of default.htm are <NOSCRIPT> and <NOFRAMES> tags. These are provided to give a small amount of backward support to really early browsers. Browsers that do not support frames and scripting will display a notice that the page requires a frames-capable browser.

Next we will look at the two included JS files used by default.htm.

sniffer.js

The sniffer.js file is used for browser detection. It contains a small amount of simple script and creates two Boolean variables. The first, bVer4, is set to true if the browser version is greater than or equal to 4. The second, bDoesDHTML is set to true only if the browser is both Internet Explorer and version 4 or later. This second variable will be used later, in menu.htm, to determine whether the expanding menu should be created. The following snifffer.js file can be found as chap24\js\sniffer.js on the companion CD.

//----------------------------
// This file creates a number of variables describing the browser.

var bVer4 = ( parseInt(navigator.appVersion) >= 4 )
var bDoesDHTML = ( (navigator.userAgent.indexOf("MSIE") >= 0) && bVer4)

cookies.js

The cookies.js file is more complex than sniffer.js. It contains two functions: SetCookie is used to write a cookie, while GetCookie is used to retrieve a cookie. This file is listed below and can be found as chap24\js\cookies.js on the companion CD.

//----------------------------
// This JS file contains basic tools for cookie manipulation.

function SetCookie(sName,sVal,sExpires,sDomain,sPath,bSecure) {
//-------------------------------------
// Set a cookie.
  document.cookie = ( sName + "=" + escape(sVal) +
     ( (sExpires) ? "; expires=" + sExpires : "" ) +
     ( (sDomain) ? "; domain=" + sDomain : "" ) +
     ( (sPath) ? "; path=" + sPath : "" ) +
     ( (bSecure) ? "; secure" : "" )    );
}

function GetCookie(sName){
//-------------------------------------
// Traverse the cookie, looking for the passed cookie name.
// If found, return the value, else return null.
  var sDelimName   = ( sName + "=" );
  var iNameLength  = sDelimName.length;
  var iCookieLength= document.cookie.length;
  var iNameStart = 0;
  while (iNameStart < iCookieLength){
    var iNameEnd = (iNameStart + iNameLength);
    if (document.cookie.substring(iNameStart, iNameEnd) == sDelimName){
      // If name found, get the associated value.
      // (from iNameEnd  to next ; or end of cookie)
      var iValueEnd = document.cookie.indexOf (";", iNameEnd);
      if (iValueEnd == -1){ iValueEnd = document.cookie.length }
      return unescape(document.cookie.substring(iNameEnd, iValueEnd));
    }
    iNameStart = ( document.cookie.indexOf(" ", iNameStart) + 1 );
    if (iNameStart == 0) break;
  }
  return null;
}

The SetCookie function is fairly straightforward and is used by custom.htm. It takes six arguments, the first two of which (sName and sVal) are required. The arguments are used to set the parameters of the cookie: sName is the cookie name, sVal is the value, sExpires is the expiration date, sDomain and sPath are the domain and path, and bSecure determines whether the cookie is only accessible over a secure connection. Each variable that starts with s accepts a string, while bSecure takes a Boolean value. If an empty string or null is passed for any of the optional arguments, it is not used. The value of the cookie is encoded with the escape method to ensure that it does not contain any problematic characters.

The GetCookie function is somewhat more complex. It takes the name of the cookie to be retrieved as its only argument. Because a cookie is in fact just a long string, this function uses many string manipulation tools to accomplish its goal. It essentially steps through the cookie string character by character, looking for the name of the value it is supposed to retrieve. When it finds the name, it extracts the text that follows until it reaches the next semicolon (used to mark the end of a cookie name=value pair) or the end of file. This extracted text corresponds to the value of the cookie and is returned. If the name is never found, null is returned.

NOTE
Many cookie retrieval functions use the split method to break up the string returned by a cookie. This process is easier than the method found in cookies.js, but it is not supported in some early browsers, including Internet Explorer 3.

main.htm

The main.htm page is the home content page used on the Web site. It starts with two linked script files, frameit.js and custom.js. In addition, legal.js is used at the bottom of the Web page. The following main.htm file can be found as chap24\main.htm on the companion CD.

<HTML>
<HEAD>
<LINK REL="STYLESHEET" TYPE="text/css" HREF="css/content.css">
<SCRIPT LANGUAGE="JavaScript" SRC="js/frameit.js"></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" SRC="js/custom.js"></SCRIPT>
</HEAD>
<BODY>
<TABLE CELLSPACING="0" CELLPADDING="0">
  <TR>
    <TD ALIGN="CENTER">
      <IMG SRC="img/book.jpg" WIDTH="104" HEIGHT="130"
           ALT="Book Cover Image" BORDER="1" ALIGN="LEFT">
      <H2>Dynamic HTML in Action, 2<SUP>nd</SUP> Edition</H2>
      <FORM>
      <SELECT onchange="var sVal=this.options[this.selectedIndex].value;
                        if (sVal != `-'){window.location.href=sVal}
                        else{this.selectedIndex=0;return false}">
        <OPTION VALUE="-">Select a Destination
        <OPTION VALUE="-">--------------------
        <OPTION VALUE="../sitebuilder/default.htm">SBN Home
        <OPTION VALUE="../workshop/default.htm">SBN Workshop
        <OPTION VALUE="../Gallery/default.htm">SBN Gallery
        <OPTION VALUE="../tools/">Tools
        <OPTION VALUE="authors.htm">About the Authors
        <OPTION VALUE="links.htm">Links
        <OPTION VALUE="custom.htm">Customize
      </SELECT>
      </FORM>
    </TD>
  </TR>
  <TR>
    <TD>
      <P>Welcome to the home page for
      <I>Dynamic HTML in Action, 2<SUP>nd</SUP> Edition</I>.
      <P>This site gives you access to many of the resources mentioned in
      the book. From here you can view the electronic version of the
      book, see the sample files for each chapter, get quick access to
      some of the tools we discuss, view the Site Builder Network
      Workshop, and even find out more about the authors! Click on an
      item in the Table of Contents on the left and enjoy!
    </TD>
  </TR>
</TABLE>
<SCRIPT LANGUAGE="JavaScript" SRC="js/legal.js"></SCRIPT>
</BODY>
</HTML>

One of the most interesting features of main.htm is the drop-down list box that can be used for navigation. When a user selects one of the items in the select box (other than the instructions at the top and the separator line), the page automatically navigates to the selected location.

All of this functionality is accomplished in the onchange event handler on the SELECT element. When one of the options is chosen, the value of that option is assigned to the sVal variable with the code sVal=this.options[this.selectedIndex].value. (See Chapter 23 for an explanation of this code.) If the user selects the separator line, the value of sVal will be set to a dash character (-) and the SELECT element is set to display the first item in the list with the code this.selectedIndex=0. Otherwise, the window navigates to the chosen item.

frameit.js

The frameit.js file is used by the content pages of the site. When any of the pages linking to frameit.js are loaded outside the context of the correct frameset, this script loads default.htm and passes to it the name of the file that was incorrectly loaded. There are many situations in which this can be useful. For example, a link returned by a search engine to a Web page will normally cause the page to be loaded in a window by itself. A script like frameit.js ensures the page is loaded in the proper context of our sample site's frameset. The following frameit.js file can be found as chap24\js\frameit.js on the companion CD.

//---------------------------------------------------------------
// This script should be included in files destined for the main frame.
// It ensures the file appears in the proper frameset if loaded by itself.

sLoc=window.location.href;

if (top.location.href==sLoc){
  //-------------------------------------------------------------
  // Retrieve file name only-NS3 does not allow "file://" in URL

  iLastBack = sLoc.lastIndexOf(`\\');
  iLastForw = sLoc.lastIndexOf(`/');
  iLastSlash=( (iLastForw > iLastBack) ? iLastForw : iLastBack );
  sFName = sLoc.substring(iLastSlash+1);

  //-------------------------------------------------------------
  // Navigate to default.htm and pass it the name of the current file.

  top.location.href="default.htm#"+sFName;
}

The majority of the script is only activated if top.location.href is equal to window.location.href (which is only true when the current page is not contained in any frames). If this is the case, the script extracts the name of the current file from the current URL by taking everything after the last slash or backslash. The browser is then pointed to a new URL containing default.htm, a hash mark (#), and the name of the current content file found above. The hash mark is normally used to indicate a bookmark, but in this case it is used as a method of passing an argument to an HTML page. The content of the URL after the hash mark can be accessed with the location.hash property. A similar and useful property is location.search, which returns any text after a question mark in the URL.

legal.js

Many Web sites have components that are used on most or all of the pages in the site. One common example is a legal notice at the bottom of every page. The legal.js file is a simple file designed to make it easy to keep an up-to-date legal notice at the bottom of our sample site's content pages. You need to change only the text in legal.js whenever the copyright notice needs to be updated, instead of needing to change every page in the site. This technique is also useful for including other shared content, such as a navigation bar or advertising banner. One additional advantage of this technique is that the JS file will be cached on the client and downloaded only when there is an update. Because the data does not have to be re-downloaded with every page, the result is a faster-performing Web site, especially if there is a fairly large amount of content replicated on every page. The following legal.js file can be found as chap24\js\legal.js on the companion CD.

//----------------------------
// This file writes a copyright notice to the page.

sCpy=("<P><FONT SIZE=`-1'>"+
      "&#169;1999  Eric Schurman and Bill Pardi. All rights reserved."+
      "</FONT>")
document.write(sCpy)

NOTE
This goal of including common content is often accomplished on the server instead of the client with server-side includes. Most Web servers support a technology in which a link can be made from within a Web page that points to a second file on the server. This second file is then incorporated into the first at the location of the link. The advantage of this technique is that it does not require any scripting on the client—only standard HTML is sent to the browser.

menu.htm

The menu.htm page provides the navigation for the Web site. Let's look at the code used in this page. This code can be found in the file chap24\menu.htm on the companion CD.

<HTML>
<HEAD>
<LINK REL="STYLESHEET" TYPE="text/css" HREF="css/menu.css">
<TITLE>Menu</TITLE>
<SCRIPT LANGUAGE="JavaScript">
//----------------------------------------------
// If loaded by itself, load default.htm instead.
if (top.location.href == window.location.href)
  { top.location.href="default.htm" }
</SCRIPT>

<SCRIPT LANGUAGE="JavaScript" SRC="js/sniffer.js"></SCRIPT>
<SCRIPT LANGUAGE="JavaScript"><!--
//-----------------------------------------------
// If browser supports this type of DHTML, hide menu items, do mouseover
// style effects and images, and and make the expanding menus.
if(bDoesDHTML){
  sStyle=(".off{display:none} .on{display:block}" +
          "a:link {text-decoration:none}" +
          "a:visited {text-decoration:none}" +
          "a:hover {text-decoration:underline; color:red}" +
          "a:active {text-decoration:underline; color:red}")
  document.write("<STYLE>"+sStyle+"</STYLE>");
  window.onload=Function("MakeExpanding()");
}

function MakeExpanding(){
  //--------------------------------------
  // Add click handler to all items of class L1.
  var oDA=document.all;
  for (i in oDA){
    if (oDA[i].className=="L1"){
      oDA[i].onclick=Function("ToggleMenu(this)");
      oDA[i].href="javascript:;"
    }
  }
}

function ToggleMenu(oHead){
  var oAll=document.all;
  iIndex=oHead.sourceIndex;
  if (oAll(iIndex+4).className=="off"){
    oAll(iIndex).src="img/open.gif";
    oAll(iIndex+4).className="on";
  }
  else {
    oAll(iIndex).src="img/closed.gif";
    oAll(iIndex+4).className="off";
  }
}
//-->
</SCRIPT>
</HEAD>
<BODY LEFTMARGIN="0" TOPMARGIN="0" TEXT="black" BGCOLOR="#CCCCFF">
<CENTER><FONT SIZE="+3"><B>TOC</B></FONT></CENTER>
<TABLE CELLSPACING="0" CELLPADDING="0">
  <TR><TD><img src="images/grayvellip.jpg" width=3 height=13 border=0quot;1"></TD>
    <TD>
     <BR><A HREF="main.htm" TARGET="main"><B>Home</B></A>
     <BR><A HREF="authors.htm" TARGET="main"><B>About the Authors</B></A>
     <BR><A HREF="links.htm" TARGET="main"><B>Useful Links</B></A>
     <BR><A HREF="../tools/" TARGET="main"><B>Tools</B></A>
     <BR><A HREF="custom.htm" TARGET="main"><B>Customize</B></A>
      </TD>
  </TR>
</TABLE>

<A CLASS="L1" TITLE="Site Builder Network" TARGET="main">
<img src="images/grayvellip.jpg" width=3 height=13 border=0"9" BORDER="0"
><B>Site Builder Network</B></A><BR>
<TABLE CELLPADDING="0" CLASS="off">
  <TR><TD><img src="images/grayvellip.jpg" width=3 height=13 border=0"1"></TD>
      <TD>
        <FONT SIZE="-1">
        <A HREF="../SiteBuilder/default.htm" TARGET="main">Home</A><BR>
        <A HREF="../workshop/default.htm" TARGET="main">Workshop</A><BR>
        <A HREF="../Gallery/default.htm" TARGET="main">Gallery</A><BR>
        </FONT>
    </TD>
  </TR>
</TABLE>

<A CLASS="L1" TITLE="Access to each chapter's files" TARGET="main">
<img src="images/grayvellip.jpg" width=3 height=13 border=0"9" BORDER="0"
><B>Code Listings</B></A><BR>
<TABLE CELLPADDING="0" CLASS="off">
  <TR><TD><img src="images/grayvellip.jpg" width=3 height=13 border=0"1"></TD>
      <TD>
        <FONT SIZE="-1">
        <A HREF="../chap01/" TARGET="main">Chapter 1</A><BR>
        <A HREF="../chap02/" TARGET="main">Chapter 2</A><BR>

        <A HREF="../chap23/" TARGET="main">Chapter 23</A><BR>
        <A HREF="../chap24/" TARGET="main">Chapter 24</A><BR>
        </FONT>
    </TD>
  </TR>
</TABLE>
</BODY>
</HTML>

NOTE
All of the links in this site are either absolute (specifying the entire URL) or relative (specifying a location relative to the current Web page). If these pages had been hosted on an actual Web server, we would have used a variation of absolute links to point to files on the site. It is possible to specify a directory off the root of a particular Web site simply by prefacing the directory name with a forward slash. Thus, an anchor on any page on the microsoft.com Web site can refer to a file found at microsoft.com/ie/ie.htm simply by using the code HREF="/ie/ie.htm". Another example is that any page at any directory level can refer to a file named main.css in a css directory off the root of the site by using the path /css/main.css. The same option can be used by SCRIPT blocks to link to JS files. One key advantage of this is that an HTM file can be moved to any directory and these links will not break. (We did not use this technique in this chapter because it does not work on a CD in Netscape Navigator.) In addition, most Web server software will let virtual roots or virtual directories be created. These are directories at any level of the directory tree that are treated as though they lived off the root of the current Web server. These directories can be accessed using the method described above.

Because menu.htm is not terribly useful by itself, the first block of script in the file simply ensures that the file is loaded in the correct frameset. Next, sniffer.js is loaded and a test is performed to check if the browser supports the necessary functionality for the expandable menu. If it does, two things happen.

First a new style sheet is written to the page. This style sheet contains the .on and .off classes that are used to make menu items display and disappear. Note that the tables containing second level menu items have the .off class. When this style sheet is written to the page, the second-level menu items are not displayed as the page loads. If the style sheet is not written to the page, the tables are displayed normally. The style sheet also contains rules that prevent an anchor from being underlined until the mouse moves over it, at which time they are underlined and highlighted.

Next the line window.onload=Function("MakeExpanding()"); causes the MakeExpanding function to be called when the window finishes loading. This function completes preparation for the expanding menus. Note that the normal HTML on the page does not have event handlers or any code to cause the expanding menus to function. The MakeExpanding function adds the necessary code to the page. It accomplishes this by iterating through the all collection and checking every element on the page. If an element has the class L1 (as do the anchors surrounding the level one headings), it is assigned an event handler that causes it to call the ToggleMenu function when clicked. It is also assigned an HREF attribute of javascript:;. If an anchor does not have an HREF attribute, it appears like normal text—not underlined and not clickable. Giving it an HREF attribute makes it clickable. However, we don't want a click on the anchor to cause the browser to navigate away from the current page, so we use an HREF that causes the page to do nothing. When an HREF contains a value that begins with http: the browser navigates to the specified location. When it contains a value starting with javascript: the browser executes the code that follows. Thus, the anchor <A HREF="javascript:alert(`hi')">Show alert</A> would cause an Alert dialog box to appear containing the text hi. This functionality is supported in version 3.02 and later of Internet Explorer and version 3 and later of Netscape. The semicolon in JavaScript is a command that essentially means "do nothing." Therefore, the HREF javascript:; causes the anchor to be clickable, but does not tell it to do anything when clicked. The MakeExpanding function adds an onclick event handler that actually handles calling the ToggleMenu function to expand and collapse the menu. The ToggleMenu function toggles the expanding items open and closed and changes the arrow image to point down or point right. It accepts one parameter—the anchor that was clicked—and it determines the index of the item in the all collection. The image to be changed and the table to be displayed or hidden are always a set number of items after this index. They are accessed through the all collection, and the menu item is toggled on or off depending on the current state.

One other notable technique in menu.htm is that some of the HTML tags are broken up so that the ending > character is on the following line, immediately preceding the < character of the next tag. If a line break or a space separates either two tags within an anchor or the contents of an anchor from the opening <A> tag, an underlined extra space is visible. On a normal Web page, we would probably have simply put both tags on the same line, but this was not an option because of line length limits in this book. In any case, breaking a tag across multiple lines is a fairly common technique.

custom.htm

The custom.htm file allows the user to customize the appearance of some pages on the site. The changes can then be saved as a cookie to the user's system and retained for future use. This file can be found as chap24\custom.htm on the companion CD, and the page is shown in Figure 24-2.

<HTML>
<HEAD>
<LINK REL="STYLESHEET" TYPE="text/css" HREF="/chap24/css/content.css">
<SCRIPT LANGUAGE="JavaScript" SRC="js/frameit.js"></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" SRC="js/custom.js"></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" SRC="js/sniffer.js"></SCRIPT>
<SCRIPT LANGUAGE="JavaScript">
<!--
var sFontFamly = "body,td{font-family:arial;} "
var sFontColor = "body,td{color:black;} "
var sBackColor = "body,td{background-color:white;} "
function Commit(){
  if (bVer4){
    //------------------------------
    // Check to make sure style choices OK, then save.
    if ( sFontColor.substr(sFontColor.lastIndexOf(":") ) ==
         sBackColor.substr(sBackColor.lastIndexOf(":") ) ){
      alert("Please make sure the font and background colors differ.")
    }
    else{
      top.sCstmStyle=(sFontFamly+sFontColor+sBackColor);
      top.SetCookie("CstmStyle",top.sCstmStyle,
                    "Fri, 31 Dec 2010 23:59:59 UTC","","","");
      location.reload();
    }
  }
  else{alert("These features require a version 4 or later browser.")}
}

function Select(oWhich, oItem){
  //------------------------------
  // If a legitimate item (not with value -) is selected, assign its
  // value to the variable passed as oWhich.
  var sItem = oItem.options[oItem.selectedIndex].value;
  if (sItem != `-'){ eval(oWhich+"=sItem") }
  else{ oItem.selectedIndex=0;return false }
}
//-->
</SCRIPT>
</HEAD>
<BODY BGCOLOR="White" TEXT="Black">
<H1>Personalization</H1>
<P>This page allows users of version 4 and later browsers to personalize
the look and feel of many of the pages in this site. Information about
any changes made is stored in cookies.

<FORM>
<BR>Select a Font
<SELECT ONCHANGE="Select(`sFontFamly',this)">
  <OPTION VALUE="body,td{font-family:arial;} ">Arial
  <OPTION VALUE="body,td{font-family:times;} ">Times
  <OPTION VALUE="body,td{font-family:courier;} ">Courier
</SELECT>
<BR>Select a Font Color
<SELECT ONCHANGE="Select(`sFontColor',this)">
  <OPTION VALUE="body,td{color:black;} ">Black
  <OPTION VALUE="body,td{color:blue;} ">Blue
  <OPTION VALUE="body,td{color:red;} ">Red
  <OPTION VALUE="body,td{color:white;} ">White
</SELECT>
<BR>Select a Background Color
<SELECT ONCHANGE="Select(`sBackColor',this)">
  <OPTION VALUE="body,td{background-color:white;} ">White
  <OPTION VALUE="body,td{background-color:blue;} ">Blue
  <OPTION VALUE="body,td{background-color:red;} ">Red
  <OPTION VALUE="body,td{background-color:black;} ">Black
</SELECT>
<BR><INPUT TYPE="BUTTON" VALUE="Commit Changes"
           onclick="Commit()">
<BR><INPUT TYPE="BUTTON" VALUE="Reset to Default"
           onclick="top.sCstmStyle=``;location.reload()">
</FORM>
<SCRIPT LANGUAGE="JavaScript" SRC="js/legal.js"></SCRIPT>
</BODY>
</HTML>

Click to view at full size.

Figure 24-2. This page allows customization by the user.

When the user selects an option from one of the drop-down lists, the chosen value is saved to either the sFontFamly, sFontColor, or sBackColor variable. When the Commit Changes button is clicked, the Commit function is run. This function first checks to see whether the chosen background and font colors conflict. If they do not, the chosen options are saved in a variable in the top frame and to a cookie. The page is then refreshed. The variables in the top frame are referenced by prefixing the variable with top. Other frames could have been referenced by substituting the name of the frame for top. The name of the frame can be set by the NAME attribute in a <FRAME> tag. The keyword parent is used to refer to the parent of the current frameset, which in this case would have been the same as top.

The cookie is set by calling the SetCookie function, which was loaded in the top frame. Note that one of the parameters for SetCookie is an explicit date that follows the Universal Coordinated Time (UTC) format. To guarantee that you have a UTC-compliant date, use a JavaScript DATE object and the getUTCDate method.

custom.js

The custom.js file is a very simple file used by the content pages. It checks to see whether any custom style has been specified and if so, writes a style sheet to the page. You can find this file as chap24\js\custom.js on the companion CD.

//----------------------------
// Write any custom style sheet specified by user.
if ( top.sCstmStyle != null ) {
  document.write("<STYLE>"+top.sCstmStyle+"</STYLE>")
}

authors.htm and links.htm

These are very simple content pages that have no special features. They contain HTML as well as links to frameit.js, custom.js, and legal.js.

Well, that's it. If you made it all the way through the book, you should have a pretty solid idea of how to work with many of the most popular technologies found on the Web. Browsers, the Web, and the Internet as a whole are a tremendously exciting area, from the perspectives of both users and programmers. The future promises to be at least as exciting as the past, given the increasing globalization of the Web, the spread of corporate intranets, the growing availability of high-speed connections from home, and the constantly changing set of available tools and technologies. Whether your interest is as simple as creating a personal home page or as complex as creating a full-blown, database-driven, intranet Web site, Web page development should be a fun and rewarding endeavor.


Appendix A -- Troubleshooting

This appendix identifies problems commonly encountered when working with script, images, and HTML, and it offers suggestions for avoiding them. For additional troubleshooting information on these and other topics related to working on the Web, check the resources and tools listed in Appendix B.

A Boolean Expression Doesn't Evaluate As Expected

A common mistake in JScript, especially in an if statement, is to use the assignment operator (=, a single equal sign) in a Boolean expression instead of the equality operator (==, two equal signs). For example, assuming that variable a has a value of 4, you might mistakenly write this expression to set up an alert:

if (a=5){alert("!")}

This line does not test for equality between a and 5, however. Instead, it assigns the value 5 to a. The expression will not evaluate to false, and thus the alert is always generated.

The correct expression is the following:

if (a==5){alert("!")}

This expression tests for equality and generates the alert only if a is equal to 5. Since a equals 4, the alert is not generated.

To review the logical operators commonly used in Boolean expressions or to find more information about writing if statements, refer to Chapter 9.

A Style Doesn't Change When Set

When you work with CSS, you can address an attribute in two ways. In in-line HTML and in style sheets, the specific attribute name should be lowercase, with a hyphen between the words that comprise the name. A colon separates the attribute name from the value being assigned to it, as shown here for font-style:

<SPAN ID="span1" STYLE="font-style: italic">

In script, you access a CSS attribute through its corresponding property in the Dynamic HTML Object Model, as explained in Chapter 15. The name of the property and the name of the attribute can differ. Hyphens are not used in property names, and any letter that followed a hyphen in the corresponding attribute name is capitalized in the property name. (Thus, the font-style attribute corresponds to the fontStyle property.) In script code, you must use an equal sign to separate the property name from the value being assigned to it, and you must enclose in quotation marks any values that are not numbers or variable names, as shown here:

span1.style.fontStyle="italic"

If you use the wrong naming convention or the wrong separator, you will find that the style is not correctly set. For example, if we had omitted the quotation marks around the italic setting in the preceding line, we would have received the error message `italic' is undefined. A different error would have resulted from using a colon as the separator instead of the equal sign.

The Browser Says an Object Is Not an Object

Your browser might occasionally generate an error message telling you that an element of your code is not an object. This error usually results from having either multiple objects with the same name or no object with the specified name. Code Listing A-1 offers an example.

Code Listing A-1.

<HTML>
<HEAD>
<TITLE>Listing A-1</TITLE>
</HEAD>
<BODY>
<SPAN ID="span1">This is a span.</SPAN>
<SPAN ID="span1">This is another span.</SPAN>
<SCRIPT LANGUAGE="JavaScript">
span1.style.fontStyle="italic"
</SCRIPT>
</BODY>
</HTML>

When you run Code Listing A-1 in Microsoft Internet Explorer, the error message `span1.style' is not an object appears because the code contains more than one object with the name span1. As a result, Internet Explorer cannot determine which object it should change. When Code Listing A-1 is displayed in Netscape Navigator, the Communicator Console (if visible) will display the error span1 is not defined. You can access the Communicator Console by typing javascript: into the Go to field (similar to the Address field in Internet Explorer). When accessing a nonexistent object in Netscape Navigator, sometimes no error message will result and the script appears to do nothing. If you are having problems using objects across browsers, you might look into helpful third-party tools, such as Scott Isaac's DHTMLLib, available at www.insidedhtml.com.

The Browser Expects a Parenthesis or a Curly Brace

When you receive a message reflecting this type of error, you'll often notice that the browser is referring to a line of code that does not contain script. It does so because a parenthesis or a curly brace should have been included in a previous line. As an example, look at Code Listing A-2.

Code Listing A-2.

<HTML>
<HEAD>
<TITLE>Listing A-2</TITLE>
<SCRIPT LANGUAGE="JavaScript">
<!--
function test()
alert("This is an alert!"
//-->
</SCRIPT>
</HEAD>
</HTML>

Code Listing A-2 contains three mistakes. When the code is executed, Internet Explorer displays an error message reading Line: 7 Char: 1 Error: Expected `{` Code: 0 while the Communicator Console for Netscape Navigator 4 displays the error line 7: missing { before function body. Because line 6 of this code defines a function, it should include the opening curly brace that is required after the set of parentheses. The next code the browser encounters is the alert on line 7; at this point, it already should have encountered the curly brace, and so it displays the error message.

If you run this code again after fixing the first mistake (by placing a curly brace after the parentheses), Internet Explorer displays the error message Line: 9 Char: 1 Error: Expected `)' Code: 0 and Navigator displays line 9: missing ) after argument list because the alert method is missing its closing parenthesis. If you run the code again after fixing this mistake, a final error is generated by the omission of the closing curly brace at the end of the function.

The Browser Says a Defined Object Is Undefined

This error is usually caused by having script reference an object before the object has been loaded or defined. You can resolve this problem in several ways. You can place your blocks of script in the HTML file after the element being addressed, or you can place all script in the head of the document but call it only after all objects have been loaded. The latter technique is often the preferred solution because it helps keep your code organized. To accomplish this, create an event handler that calls a function when the page has finished loading.

window.onload=functionName;

or

window.onload=Function("functionName()");

or, in Internet Explorer only,

<SCRIPT FOR="window" EVENT="onload">
{The script you want run, or a call to a function}
</SCRIPT>

Events Are Firing Unexpectedly

In Internet Explorer, this problem is frequently related to event bubbling (discussed in Chapter 7). For example, you might want to have something occur as the user moves the mouse pointer in and out of a table. If you simply add onmouseover and onmouseout event handlers for the table, these handlers will be triggered both by events that occur to cells within the table as well as by events that occur to the table as a whole. This is because the events that occur to cells bubble upward in the Object Model until they are handled by the parent object (the table). Code Listing A-3 and Figure A-1 demonstrate two examples of how this works.

Code Listing A-3.

<HTML>
<HEAD>
<TITLE>Listing A-3</TITLE>
</HEAD>
<BODY>
Notice that mousing between cells in the top table increments the
number of mouseovers and mouseouts.
<TABLE ID="A" BORDER="2"
  onmouseover="F1.MOver.value=parseInt(F1.MOver.value)+1"
  onmouseout="F1.MOut.value=parseInt(F1.MOver.value)+1">
  <TR><TD>Cell1</TD><TD></TD><TD>Cell2</TD></TR>
  <TR><TD>Cell3</TD><TD></TD><TD>Cell4</TD></TR>
</TABLE>
Notice that mousing between cells in the bottom table does not increment
the number of mouseovers and mouseouts. Only mouse events on the table as
a whole have an effect.
<TABLE ID="B" BORDER="2"
  onmouseover="if(!B.contains(event.fromElement))
                 {F1.MOver.value=parseInt(F1.MOver.value)+1}"
  onmouseout="if(!B.contains(event.toElement))
                {F1.MOut.value=parseInt(F1.MOut.value)+1}">
  <TR><TD>Cell1</TD><TD></TD><TD>Cell2</TD></TR>
  <TR><TD>Cell3</TD><TD></TD><TD>Cell4</TD></TR>
</TABLE>
<FORM ID="F1">
  Mouseovers: <INPUT ID="MOver" TYPE="text" VALUE="1">
  Mouseouts: <INPUT ID="MOut" TYPE="text" VALUE="1">
</FORM>
</BODY>
</HTML>

Click to view at full size.

Figure A-1. The two tables behave differently as the mouse movements interact with them.

In the first table created by Code Listing A-3, any onmouseout event received by the TABLE element causes the Mouseouts text field to be incremented. This is true whether the event was triggered for the TABLE element itself or for an element inside the table, such as a TD. If you move your mouse around in the top table, you will see the number of Mouseouts and Mouseovers increasing rapidly.

In the second table, the onmouseout event handler performs a test and increments the number of Mouseouts only if the event was not fired by an element contained within the table. In other words, the only element whose onmouseout event causes the background to change is the TABLE element itself.

NOTE
Some events do not bubble. If you are having problems with event bubbling, check the SBN Workshop Web site or the companion CD to ensure that the event in question does bubble. On the CD, see Workshop (References) and select DHTML, HTML & CSS; DHTML References; Events. To get to the online version, visit the MSDN Online Resource page at msdn.microsoft.com/resources/schurmandhtml.htm or open the file named MSDN_OL.htm on the companion CD, and choose Events.

An Image Is Displayed in Unexpected Colors

When a computer monitor is set to an 8-bit color resolution, it can display only 256 colors. For example, when a browser has the focus and has a GIF image loaded, it attempts to display the colors used in the image. If an image using a different palette is loaded, the colors in the browser are remapped to account for both images as well as the browser's palette. As a result, a palette flash might occur. Even if a flash does not occur, the image might not appear as intended because there might not be enough colors available to display all the colors in both images.

To avoid flashes or palette remapping, the image's palette should match the "browser-safe" palette (included on the companion CD in the Tools folder). This match is usually accomplished when an image is converted from high color (also known as full-color or 24-bit) to indexed color. Most image editing programs allow the designer to specify a palette when indexing an image.

Pages Take Too Long to Download

One obvious solution to this problem is to reduce the number of images on a page. That isn't always possible, of course, but it is nevertheless a good idea to evaluate the use of each image and consider whether it could be replaced with some other element. For example, before dynamic styles, often the only way to include stylized text or special text effects was to put the text in a graphic. Now that type of image can be replaced with HTML and styles, thereby significantly reducing download time.

The two most common graphics formats used on the Web are GIF and JPEG (the file extensions for these formats are .gif and .jpg, or .jpeg, respectively). Each of these two formats uses a different method of compression and thus is better suited for certain kinds of images. If your image has large areas of solid color, a GIF will usually provide the smallest file size. If your image contains a great deal of variation, such as a nature photo, a JPEG will usually produce the smallest size and best quality.

To illustrate these differences, we saved two images using the optimal format for each. You can see these images on the companion CD in the appxA folder. The first file, spots.gif, is less than 3 KB in size, and the image looks just as it should on screen. The second file, clouds.jpg, is 15 KB, and the colors in the image are smooth and bright. Now look at the same images saved in different formats.

Although the image spots.jpg looks fine, the file size is now 30 KB, 13 times as large as it was as a GIF. The clouds.gif file has expanded from the 15 KB JPG to 160 KB, and you can see severe color degradation and banding. It really pays to test different formats for your images.

Using the Structured Graphics control (discussed in Chapter 16) can also help to reduce the wait time for graphics when targeting only Internet Explorer. Structured graphics primitives can be especially helpful in replacing simple bitmapped images such as circles, squares, ovals, and so on.

Portions of an Image Cover Areas That Should Be Displayed

If you use GIF files for your images, you can make one color in the image transparent, which means that any element "behind" that image will show through the transparent color. Code Listing A-4 shows two different images in front of a background image, used in the body. Figure A-2 shows the result.

Code Listing A-4.

<HTML>
<HEAD>
<TITLE>Listing A-4</TITLE>
</HEAD>
<BODY BACKGROUND="back.gif">
<IMG SRC="dhtml.gif" WIDTH=108 HEIGHT=26 ALT="" BORDER="0">
<IMG SRC="dhtmltrans.gif" WIDTH=108 HEIGHT=26 ALT="" BORDER="0">
</BODY>
</HTML>

Click to view at full size.

Figure A-2. The second image uses transparent areas around the letters.

As you can see in Figure A-2, the first image completely blocks the background. The second image allows the background to show through around the letters. When we created the second image, we simply specified that white should be treated as transparent, resulting in the behavior shown. Typically, this is done when saving the file from an image editor.

Frames and Tables Don't Work

Frames and tables seem to cause headaches for many people. One common mistake is the never-ending frame. Content developers sometimes provide links inside a frame with no way to get out of that frame, resulting in a situation in which the same frameset is repeated, or the frames from two sites are mixed together.

The solution is to provide a way out of the frame by pointing links to the top window. For example, if a link points to www.w3.org, a direct link will open the page inside the current frame, wherever that might be. But adding TARGET="_top" to the anchor tag will open the page in the top window, replacing any frames on the page.

Another common problem is improper nesting. For frames to work, the FRAME elements should be nested inside a FRAMESET, as shown in the following code:

    <FRAMESET COLS="25%,*" FRAMESPACING=0 FRAMEBORDER="yes">
      <FRAME NAME="frame1" SRC="frame1.htm" FRAMESPACING=0>
      <FRAMESET ROWS="15%,*" FRAMESPACING=0 FRAMEBORDER="yes">
        <FRAME NAME="frame2" SRC="frame2.htm" FRAMESPACING=0>
        <FRAME NAME="frame3" SRC="frame3.htm" FRAMESPACING=0>
      </FRAMESET>
    </FRAMESET>

In tables, cells (TD elements) must be nested inside an appropriate element, such as TR, THEAD, or TFOOT, which, in turn, must be nested inside a TABLE element. If your frames or tables are not displaying properly, check to see whether the content is nested correctly. Remember that you can use borders to test frames and tables, even if you do not plan to include borders in the final version. Using a border when you are creating your page can help you see exactly how the frame or table is displayed and can also help you debug the code when problems arise.

Pages Always Have Scrollbars, Even If They Are Not Needed

A standard Internet Explorer window is drawn with a scrollbar, and you might not always need it (for example, when there is no text on the page). Typically, this is not an issue in Netscape Navigator. You can eliminate the scrollbar by setting the SCROLL attribute in the BODY element to no. However, be careful when using this method because it completely disables scrollbars, meaning that users might be unable to access some of the page if their screens are in a lower resolution, or if they are using different fonts than you.

There are a few ways to make a scrollbar automatically appear only when necessary. If you are using frames on a page, you can set the SCROLLING attribute of a FRAME element to auto and a scrollbar will appear only if the contents of the frame extend beyond the borders of the frame. On a single Web page, you can enclose the entire contents of the page in one large DIV element that is 100 percent of the width and height of the screen and has its overflow CSS attribute set to auto. If you use this method, you will want to set the TOPMARGIN and LEFTMARGIN attributes of the BODY element to 0 and its SCROLL attribute to no to make sure that the DIV extends to the edge of the window. The following piece of code shows a portion of a file that uses this second method.

    <BODY SCROLL="no" LEFTMARGIN="0" TOPMARGIN="0">
    <DIV STYLE="overflow:auto;width:100%;height:100%">
    [The document content goes here]
    <DIV>
    </BODY>


Appendix B -- Tools

This appendix lists many of the tools and resources that we have found helpful. It is by no means a full description of all the tools available for working on the Web, but it should get you started and lead you to other useful information.

Many of the tools listed here are shareware or freeware and are available for downloading from a variety of sites on the Internet. Some of our favorite download sites include the following:

  • http://www.hotfiles.com

  • www.tucows.com

  • www.windows95.com

  • www.download.com

  • oak.oakland.edu

  • www.davecentral.com

HTML/Script Editors

Notepad | This very limited text editor is included with Microsoft Windows. It is sometimes referred to in jest as "Visual N++."
Allaire HomeSite | Contact www.allaire.com. This extremely flexible text editor is one of our favorites. It contains a variety of useful Web features, such as color coding of tags, powerful multiple-file search and replace, automatic tag completion, HTML validation, integration of Microsoft Internet Explorer, site and project management tools, an optional WYSIWYG view, and automatic insertion of width and height for images.
Microsoft FrontPage | Contact microsoft.com/frontpage. This suite of Web tools includes a WYSIWYG editor that outputs some of the highest-quality HTML of any WYSIWYG editor. Unlike many WYSIWYG editors, FrontPage 2000 does not modify any HTML that is hand-entered by the developer.
Microsoft FrontPage | Contact microsoft.com/ie. This WYSIWYG editor is part of a full installation of Internet Explorer. FrontPage Express is somewhat limited, but it is free and easy to use.
Microsoft Visual InterDev | Contact msdn.microsoft.com/vinterdev. This Visual Studio-based tool is a full-blown development environment that lets you easily create interactive Web sites with database connectivity based on Active Server Pages (ASP).
Microsoft Script Debugger | Contact msdn.microsoft.com/scripting. This useful tool is for debugging script and lets you trace the execution of your code and set breakpoints as well as track the current values of variables
Adobe PageMill | Contact www.adobe.com. This WYSIWYG editing tool includes a limited edition of the Adobe Photoshop image editor and a lot of clip art and animations.
Sausage Software HotDog | Contact www.sausage.com. This popular HTML editor includes a variety of wizards for easy document creation as well as colorcoding and support for third-party plug-ins.
SoftQuad HoTMetaL PRO | Contact www.softquad.com. This HTML editing tool provides three editing environments: WYSIWYG, WYSIWYG withHTML tags, and color-coded text. It also provides built-in HTML validation to ensure that your HTML code is correct.
Allaire Cold Fusion | Contact www.allaire.com. This tool enables you to easily create data-base-driven Web sites.
NetObjects Fusion | Contact www.netobjects.com. This site management and design tool allows you to work with a Web site as a whole, helping you manage everything from the individual pages to the over-all style of the site.
Macromedia Dreamweaver | Contact www.macromedia.com. This was one of the first WYSIWYG environments to produce Dynamic HTML.
Microsoft Office 97 | Contact www.microsoft.com/office. Support for HTML output has increased dramatically in Microsoft Office. Microsoft Office can be handy for many Web page needs.

Image Editors

Adobe Photoshop | Contact www.adobe.com. This image editor is the great-granddaddy of them all, and it has become the standard in the graphic design industry.
Microsoft PhotoDraw 2000 | Designed for business graphics editing needs, this newcomer is easy to use and includes over 20,000 images and pieces of clip art.
Macromedia Fireworks | A graphics program designed for the Web, Fireworks lets you work with your graphics in vector format before outputting the final image.
Jasc Software Paint Shop Pro | Contact www.jasc.com. This shareware program is very useful and comparatively inexpensive. It includes many extra tools such as built-in screen capture and batch conversion utilities as well as an image browser.
The GIMP | Contact www.gimp.org. The GNU Image Manipulation Program is a powerful, freely distributed image editor for UNIX. It includes a scripting interface and many other advanced features like multiple undo/redo. There are projects under way to port this program to the Windows platform.
Equilibrium DeBabelizer | Contact www.equilibrium.com. This tool is useful for batch-processing graphics.
Alchemy Mindworks Graphic Workshop | Contact www.mindworkshop.com. This inexpensive suite of graphics tools includes an image browser and a batch editor.
Microsoft FrontPage | Contact www.microsoft.com/frontpage. This product includes an image editor, an animated GIF editor, and a variety of other graphics tools such as an image map editor.

GIF Animation Tools

Microsoft GIF Animator | Contact microsoft.com/imagecomposer/gifanimator/gifanin.htm. This tool, which is included as part of Microsoft Image Composer (a component of FrontPage), lets you create an animated GIF from a series of other GIFs, and it will also convert AVI movies into animated GIFs.
Right to Left Software Animagic GIF | Contact rtlsoft.com. This tool optimizes animated GIF files. We have used it to compress an animated GIF to less than 2 percent of its original size, with no loss of visual quality.
Alchemy Mindworks Gif Construction Set | Contact www.mindworkshop.com. This flexible GIF editing tool lets you exercise precise control over a GIF. It includes a vari-ety of wizards to assist in the assembly of animations and alsolets you go directly into the guts of a GIF.

Screen Capture Utilities

Microsoft Windows | Some of the most basic screen capture tools come with Microsoft Windows. Simply pressing the Print Screen key copies the entire screen to the clipboard, from which you can paste the image into any image editor. Pressing Alt-Print Screencaptures only the currently active window.
Microsoft HTML Help Image Editor | Contact microsoft.com/workshop/author/htmlhelp/download.asp. This free capture utility is our favorite. It makes it very easy to capture everything from individual components of a window to a single application window to the entire screen. It includesgood cropping tools and bit depth converters.
Hyperionics HyperSnap-DX | Contact www.hyperionics.com. This tool creates still screen captures in a variety of formats. It allows you to capture DirectX games, the cursor, or an entire window (even parts thathave been scrolled off the screen).
Pedagoguery Software Gif·gIf·giF | Contact www.cafe.net/peda/ggg. This tool captures animated GIFs of actions performed on the screen. The resulting files are quite small.
Hyperionics HyperCam | Contact www.hyperionics.com. This tool creates AVI animations of actions performed on the screen.

Multimedia Tools

Adobe Premiere | Contact www.adobe.com. This movie editor is an industry stan-dard. It supports output in all standard digital video formats,including AVI and QuickTime. An animated GIF plug-in is available from the Adobe Web site.
Macromedia Shockwave, Flash, and Director | Contact www.macromedia.com. Together, these tools allow the delivery of high-quality, interactive multimedia sites over the Web, including streaming, vector-based animations with audio.
Sonic Foundry Sound Forge | Contact www.sonicfoundry.com. This full-featured sound editing tool supports many types of compression and file formats, in-cluding WAV, AVI, and NetShow ASF.

References

The Web offers many useful information sources. The SBN Workshop included on the companion CD of this book is an excellent reference; the online version, which is updated periodically, can be found at microsoft.com/workshop. At the time of this writing, the content on this site is scheduled to migrate to the Microsoft Developer Network (MSDN) at msdn.microsoft.com. The list that follows provides some additional resources. (Of course, given the changing nature of the Web, it is possible that some of these sites will be unavailable when you try to reach them.)

www.w3.org | The official Web site of the leading Web standards body. Here you can find the complete specifications for many Web standards, such as HTML, CSS, HTTP, XML, DOM, and so on.
microsoft.com/sitebuilder | This site contains articles, references, and downloadable tools for building Web sites. Content for this site is scheduled to migrate to msdn.microsoft.com, the Microsoft Developer Network Web site.
msdn.microsoft.com/scripting | Microsoft's scripting reference and tutorial site.
developer.netscape.com/library/documentation/communicator/jsref/index.htm | Netscape's JavaScript reference site. This site contains many excellent examples.
www.gamelan.com | This site is dedicated to Java, JavaScript, ActiveX, and other Internet technologies.
www.wdvl.com | The Web Developer's Virtual Library. This site contains useful information for Web designers, such as referencesfor and introductions to HTML, graphics, Java, and so on.
www.jars.com | This site contains many Web-based programs and source code listings.
 | Another great site for examples and how-to information. Covers everything from electronic commerce to HTML to JavaScript.
www.webreview.com | This site covers all aspects of creating Web sites, from graphic design issues to the technical aspects of maintaining a large-scale site.
www.zdnet.com/devhead | From Ziff Davis, a publisher of computer magazines and books, this site contains many references and includesarticles and how-to information written by some of the industry's biggest names.
msdn.microsoft.com | Microsoft Developer Network. Contains hard-core references for developers.
microsoft.com/data | Great site for information about data access technologies,such as ADO.
JavaScript: The Definitive Guide | Written by David Flanagan and published by O'Reilly & Associates, this is a great reference book on JavaScript.


Appendix C -- Components of the Dynamic HTML Object Model

This appendix provides complete lists of the objects, properties, events, methods, and collections available in the Dynamic HTML Object Model supported by Microsoft Internet Explorer 5. Detailed descriptions of the entries listed here can be found in the SBN Workshop on the companion CD; see Workshop (References); DHTML, HTML, & CSS; DHTML References. DD HTML HTMLAREA

Objects

!DOCTYPE | H1 | PARAM
A | H2 | PLAINTEXT
ACRONYM | H3 | PRE
ADDRESS | H4 | Q
APPLET | H5 | RB
AREA | H6 | RT
Attribute | HR | RUBY
B | HTML | runtimeStyle
BASE | HTMLAREA | rule
BASEFONT | I | S
BDO | IFRAME | SAMP
BGSOUND | IMG | screen
BIG | INPUT | SCRIPT
BLOCKQUOTE | INPUT type=button | SELECT
BODY | INPUT type=checkbox | selection
BR | INPUT type=file | SMALL
BUTTON | INPUT type=hidden | SPAN
CAPTION | INPUT type=image | STRIKE
CENTER | INPUT type=password | STRONG
CITE | INPUT type=radio | style
CODE | INPUT type=reset | STYLE
COL | INPUT type=submit | styleSheet
COLGROUP | INPUT type=text | SUB
COMMENT | INS | SUP
currentStyle | ISINDEX | TABLE
dataTransfer | KBD | TBODY
DD | LABEL | TD
DEL | LEGEND | TEXTAREA
DFN | LI | TextNode
DIR | LINK | TextRange
DIV | LISTING | TextRectangle
DL | location | TFOOT
document | MAP | TH
DT | MARQUEE | THEAD
EM | MENU | TITLE
EMBED | META | TR
event | navigator | TT
external | NEXTID | U
FIELDSET | NOBR | UL
FONT | NOSCRIPT | userProfile
FORM | NOFRAMES | VAR
FRAME | OBJECT | WBR
FRAMESET | OL | window
HEAD | OPTION | XML
history | P | XMP

Properties

!important | disabled | parentNode
@charset | display | parentStyleSheet
@font-face | documentElement | parentTextEdit
@import | domain | parentWindow
accessKey | dropEffect | pathname
action | dynsrc | pixelBottom
activeElement | effectAllowed | pixelHeight
align | encoding | pixelLeft
aLink | event | pixelRight
aLinkColor | expando | pixelTop
alt | face | pixelWidth
altHTML | fgColor | platform
altKey | fileCreatedDate | pluginspage
appCodeName | fileModifiedDate | port
appMinorVersion | fileSize | posBottom
appName | fileUpdatedDate | posHeight
appVersion | filter | position
autocomplete | firstChild | posLeft
availHeight | font | posRight
availWidth | fontFamily | posTop
background | fontSize | posWidth
backgroundAttachment | fontSmoothingEnabled | previousSibling
backgroundColor | fontStyle | propertyName
backgroundImage | fontVariant | protocol
backgroundPosition | fontWeight | readOnly
backgroundPositionX | form | readyState
backgroundPositionY | frame | reason
backgroundRepeat | frameBorder | recordNumber
balance | frameSpacing | recordset
behavior | fromElement | referrer
bgColor | hash | rel
bgProperties | height | repeat
border | hidden | returnValue
borderBottom | host | rev
borderBottomColor | hostname | right
borderBottomStyle | href | rightMargin
borderBottomWidth | hspace | rowIndex
borderCollapse | htmlFor | rows
borderColor | htmlText | rowSpan
borderColorDark | httpEquiv | rubyAlign
borderColorLight | id | rubyOverhang
borderLeft | imeMode | rubyPosition
borderLeftColor | indeterminate | rules
borderLeftStyle | index | screenLeft
borderLeftWidth | innerHTML | screenTop
borderRight | innerText | screenX
borderRightColor | isMap | screenY
borderRightStyle | isTextEdit | scroll
borderRightWidth | keyCode | scrollAmount
borderStyle | lang | scrollDelay
borderTop | language | scrollHeight
borderTopColor | lastChild | scrolling
borderTopStyle | lastModified | scrollLeft
borderTopWidth | layoutGrid | scrollTop
borderWidth | layoutGridChar | scrollWidth
bottom | layoutGridCharSpacing | search
bottomMargin | layoutGridLine | sectionRowIndex
boundingHeight | layoutGridMode | selected
boundingLeft | layoutGridType | selectedIndex
boundingTop | left | selectorText
boundingWidth | leftMargin | self
browserLanguage | length | shape
bufferDepth | letterSpacing | shiftKey
button | lineBreak | size
cancelBubble | lineHeight | sourceIndex
caption | link | span
cellIndex | linkColor | specified
cellPadding | listStyle | src
cellSpacing | listStyleImage | srcElement
charset | listStylePosition | srcFilter
checked | listStyleType | srcUrn
classid | loop | start
className | lowsrc | status
clear | map | style
clientHeight | margin | styleFloat
clientInformation | marginBottom | systemLanguage
clientLeft | marginHeight | tabIndex
clientTop | marginLeft | tableLayout
clientWidth | marginRight | tagName
clientX | marginTop | target
clientY | marginWidth | text
clip | maxLength | textAlign
clipBottom | media | textDecoration
clipLeft | menuArguments | textDecorationBlink
clipRight | method | textDecorationLineThrough
clipTop | Methods | textDecorationNone
closed | multiple | textDecorationOverline
code | name | textDecorationUnderline
codeBase | nextSibling | textIndent
codeType | nodeName | textJustify
color | nodeType | textTransform
colorDepth | nodeValue | tFoot
cols | noHref | tHead
colSpan | noResize | title
compact | noShade | toElement
complete | noWrap | top
content | object | topMargin
cookie | offscreenBuffering | trueSpeed
cookieEnabled | offsetHeight | type
coords | offsetLeft | uniqueID
cpuClass | offsetParent | units
cssText | offsetTop | updateInterval
ctrlKey | offsetWidth | url
cursor | offsetX | urn
data | offsetY | useMap
dataFld | onLine | userAgent
dataFormatAs | opener | userLanguage
dataPageSize | outerHTML | vAlign
dataSrc | outerText | value
defaultCharset | overflow | vcard_name
defaultChecked | overflowX | verticalAlign
defaultSelected | overflowY | visibility
defaultStatus | owningElement | vLink
defaultValue | padding | vlinkColor
defer | paddingBottom | volume
designMode | paddingLeft | vspace
dialogArguments | paddingRight | width
dialogHeight | paddingTop | wordBreak
dialogLeft | pageBreakAfter | wordSpacing
dialogTop | pageBreakBefore | wrap
dialogWidth | palette | x
dir | parent | y
direction | parentElement | zIndex

Events

onabort | ondblclick | onmousemove
onafterprint | ondrag | onmouseout
onafterupdate | ondragend | onmouseover
onbeforecopy | ondragenter | onmouseup
onbeforecut | ondragleave | onpaste
onbeforepaste | ondragover | onpropertychange
onbeforeprint | ondragstart | onreadystatechange
onbeforeunload | ondrop | onreset
onbeforeupdate | onerror | onresize
onblur | onerrorupdate | onrowenter
onbounce | onfilterchange | onrowexit
oncellchange | onfinish | onrowsdelete
onchange | onfocus | onrowsinserted
onclick | onhelp | onscroll
oncontextmenu | onkeydown | onselect
oncopy | onkeypress | onselectstart
oncut | onkeyup | onstart
ondataavailable | onload | onsubmit
ondatasetchanged | onlosecapture | onunload
ondatasetcomplete | onmousedown |

Methods

add | empty | queryCommandIndeterm
addBehavior | execCommand | queryCommandState
AddChannel | execCommand | queryCommandSupported
AddDesktopComponent | execScript | queryCommandValue
AddFavorite | execScript | recalc
addImport | expand | refresh
addReadRequest | findText | releaseCapture
addRule | firstPage | reload
alert | focus | remove
appendChild | forward | removeAttribute
applyElement | getAdjacentText | removeBehavior
assign | getAttribute | removeChild
attachEvent |  | removeExpression
back | getBookmark | removeNode
blur | getBoundingClientRect | removeRule
clear | getClientRects | replaceAdjacentText
 | getData | replaceChild
clearData | getExpression | replaceNode
clearInterval | go | reset
clearRequest | hasChildNodes | resizeBy
clearTimeout | ImportExportFavorites | replace
click | inRange | resizeTo
cloneNode | insertAdjacentElement | scroll
close | insertAdjacentHTML | scrollBy
collapse | insertAdjacentText | scrollIntoView
compareEndPoints | insertBefore | scrollTo
componentFromPoint | insertRow | select
confirm | isEqual | setAttribute
contains | IsSubscribed | setCapture
createCaption | item | setData
createControlRange | javaEnabled | setEndPoint
createDocumentFragment | lastPage | setExpression
createElement | move | setInterval
createRange | moveBy | setTimeout
createStyleSheet | moveEnd | showHelp
createTextNode | moveStart | showModalDialog
createTextRange | moveToBookmark | moveTo
createTFoot | moveToElementText | showModelessDialog
createTHead | moveToPoint | splitText
deleteCaption | navigate | swapNode
deleteCell | NavigateAndFind | tags
deleteRow | nextPage | taintEnabled
deleteTFoot | open | urns
deleteTHead | parentElement | write
detachEvent | pasteHTML | start
doReadRequest | previousPage | stop
doScroll | print | submit
duplicate | prompt | writeln
elementFromPoint | queryCommandEnabled |

Collections

all

anchors

applets

areas

attributes

behaviorUrns

bookmarks

boundElements

cells

childNodes

children

controlRange

elements

embeds

filters

forms

frames

images

imports

links

mimeTypes

options

plugins

rows

rules

scripts

styleSheets

tBodies

TextRectangle


Appendix D -- The First 256 Character Entities

The following is a list of the first 256 character entities. Many letters and symbols commonly used in most western languages (like English) can be found here. A sample HTML file on the CD in AppndxD\appd.htm demonstrates all of these entities. A more complete list of character entities can be found in the SBN Workshop on the companion CD at Workshop (References); DHTML, HTML, & CSS; HTML References; Character Sets. Note that a few of the characters will display differently in different fonts or on different operating systems.

NOTE
The indexes from &#129; through &#159 are officially "reserved" characters and are undefined. However, both Netscape Navigator and Microsoft Internet Explorer display them as shown below.

Displays As | Numerical Identifier | Named Entity | Description
&#00; | Not Used
&#01; | Not Used
&#02; | Not Used
&#03; | Not Used
&#04; | Not Used
&#05; | Not Used
&#06; | Not Used
&#07; | Not Used
&#08; | Not Used
&#09; | Horizontal tab
&#10; | Line feed
&#11; | Not Used
&#12; | Not Used
&#13; | Carriage Return
&#14; | Not Used
&#15; | Not Used
&#16; | Not Used
&#17; | Not Used
&#18; | Not Used
&#19; | Not Used
&#20; | Not Used
&#21; | Not Used
&#22; | Not Used
&#23; | Not Used
&#24; | Not Used
&#25; | Not Used
&#26; | Not Used
&#27; | Not Used
&#28; | Not Used
&#29; | Not Used
&#30; | Not Used
&#31; | Not Used
&#32; | Space
! &#33; Explanation point
" &#34; &quot; Quotation mark
# &#35; Number sign
$ &#36; Dollar sign
% &#37; Percent sign
& &#38; &amp; Ampersand
' &#39; Apostrophe
( &#40; Left parenthesis
) &#41; Right parenthesis
* &#42; Asterisk
+ &#43; Plus sign
, &#44; Comma
- &#45; Hyphen
. &#46; Period (fullstop)
/ &#47; Solidus (forwardslash)
0 | &#48; | Number 0
1 | &#49; | Number 1
2 | &#50; | Number 2
3 | &#51; | Number 3
4 | &#52; | Number 4
5 | &#53; | Number 5
6 | &#54; | Number 6
7 | &#55; | Number 7
8 | &#56; | Number 8
9 | &#57; | Number 9
: &#58; Colon
; &#59; Semicolon
< &#60; &lt; Less than
= &#61; Equals sign
> &#62; &gt; Greater than
? &#63; Question mark
@ &#64; Commercial at
A | &#65; | Capital A
B | &#66; | Capital B
C | &#67; | Capital C
D | &#68; | Capital D
E | &#69; | Capital E
F | &#70; | Capital F
G | &#71; | Capital G
H | &#72; | Capital H
I | &#73; | Capital I
J | &#74; | Capital J
K | &#75; | Capital K
L | &#76; | Capital L
M | &#77; | Capital M
N | &#78; | Capital N
O | &#79; | Capital O
P | &#80; | Capital P
Q | &#81; | Capital Q
R | &#82; | Capital R
S | &#83; | Capital S
T | &#84; | Capital T
U | &#85; | Capital U
V | &#86; | Capital V
W | &#87; | Capital W
X | &#88; | Capital X
Y | &#89; | Capital Y
Z | &#90; | Capital Z
[ &#91; Left square bracket
\ &#92; Reverse solidus (backslash)
] &#93; Right square bracket
^ &#94; Caret
_ &#95; Horizontal bar (underscore)
` &#96; Acute accent
a | &#97; | Lowercase a
b | &#98; | Lowercase b
c | &#99; | Lowercase c
d | &#100; | Lowercase d
e | &#101; | Lowercase e
f | &#102; | Lowercase f
g | &#103; | Lowercase g
h | &#104; | Lowercase h
i | &#105; | Lowercase i
j | &#106; | Lowercase j
k | &#107; | Lowercase k
l | &#108; | Lowercase l
m | &#109; | Lowercase m
n | &#110; | Lowercase n
o | &#111; | Lowercase o
p | &#112; | Lowercase p
q | &#113; | Lowercase q
r | &#114; | Lowercase r
s | &#115; | Lowercase s
t | &#116; | Lowercase t
u | &#117; | Lowercase u
v | &#118; | Lowercase v
w | &#119; | Lowercase w
x | &#120; | Lowercase x
y | &#121; | Lowercase y
z | &#122; | Lowercase z
{ &#123; Left curly brace
| &#124; Vertical bar
} &#125; Right curly brace
~ &#126; Tilde
&#127; | Not Used
&#128; | Not Used
• &#129;
, &#130;
ƒ | &#131;
„ &#132;
... &#133; Ellipsis
† &#134;
‡ &#135;
^ &#136; Caret
‰ &#137;
Š | &#138;
< &#139;
Œ | &#338;
• &#141;
• &#142;
• &#143;
• &#144;
` &#145;
` &#146;
" &#147;
" &#148;
• &#149; Bullet
_ &#150;
— &#151;
~ &#152;
™ &#153; Trademark
š | &#154;
> &#155;
œ | &#156;
&#157;
&#158;
Ÿ | &#159;
&#160; | &nbsp; | Nonbreaking space
¡ &#161; &iexcl; Inverted exclamation
¢ &#162; &cent; Cent sign
£ &#163; &pound; Pound sterling
¤ &#164; &curren; General currency sign
¥ &#165; &yen; Yen sign
¦ &#166; &brvbar;
or &brkbar; 		Broken vertical bar
§ &#167; &sect; Section sign
¨ &#168; &uml;
or &die; 		Diæresis / Umlaut
© &#169; &copy; Copyright
ª | &#170; | &ordf; | Feminine ordinal
« &#171; &laquo; Left angle quote, guillemot left
¬ &#172; &not Not sign
&#173; | &shy; | Soft hyphen
® &#174; &reg; Registered trademark
¯ &#175; &macr;
or &hibar; 		Macron accent
° &#176; &deg; Degree sign
± &#177; &plusmn; Plus or minus
² | &#178; | &sup2; | Superscript two
³ | &#179; | &sup3; | Superscript three
´ &#180; &acute; Acute accent
µ | &#181; | &micro; | Micro sign
¶ &#182; &para; Paragraph sign
· &#183; &middot; Middle dot
¸ &#184; &cedil; Cedilla
¹ | &#185; | &sup1; | Superscript one
º | &#186; | &ordm; | Masculine ordinal
» &#187; &raquo; Right angle quote, guillemot right
¼ | &#188; | &frac14; | Fraction one-fourth
½ | &#189; | &frac12; | Fraction one-half
¾ | &#190; | &frac34; | Fraction three-fourths
¿ &#191; &iquest; Inverted question mark
À | &#192; | &Agrave; | Capital A, grave accent
Á | &#193; | &Aacute; | Capital A, acute accent
Â | &#194; | &Acirc; | Capital A, circumflex
Ã | &#195; | &Atilde; | Capital A, tilde
Ä | &#196; | &Auml; | Capital A, diæresis / umlaut
Å | &#197; | &Aring; | Capital A, ring
Æ | &#198; | &AElig; | Capital AE ligature
Ç | &#199; | &Ccedil; | Capital C, cedilla
È | &#200; | &Egrave; | Capital E, grave accent
É | &#201; | &Eacute; | Capital E, acute accent
Ê | &#202; | &Ecirc; | Capital E, circumflex
Ë | &#203; | &Euml; | Capital E, diæresis / umlaut
Ì | &#204; | &Igrave; | Capital I, grave accent
Í | &#205; | &Iacute; | Capital I, acute accent
Î | &#206; | &Icirc; | Capital I, circumflex
Ï | &#207; | &Iuml; | Capital I, diæresis / umlaut
Ð | &#208; | &ETH; | Capital Eth, Icelandic
Ñ | &#209; | &Ntilde; | Capital N, tilde
Ò | &#210; | &Ograve; | Capital O, grave accent
Ó | &#211; | &Oacute; | Capital O, acute accent
Ô | &#212; | &Ocirc; | Capital O, circumflex
Õ | &#213; | &Otilde; | Capital O, tilde
Ö | &#214; | &Ouml; | Capital O, diæresis / umlaut
× &#215; &times; Multiply sign
Ø | &#216; | &Oslash; | Capital O, slash
Ù | &#217; | &Ugrave; | Capital U, grave accent
Ú | &#218; | &Uacute; | Capital U, acute accent
Û | &#219; | &Ucirc; | Capital U, circumflex
Ü | &#220; | &Uuml; | Capital U, diæresis / umlaut
Ý | &#221; | &Yacute; | Capital Y, acute accent
Þ | &#222; | &THORN; | Capital Thorn, Icelandic
ß | &#223; | &szlig; | Lowercase sharp s, German sz
à | &#224; | &agrave; | Lowercase a, grave accent
á | &#225; | &aacute; | Lowercase a, acute accent
â | &#226; | &acirc; | Lowercase a, circumflex
ã | &#227; | &atilde; | Lowercase a, tilde
ä | &#228; | &auml; | Lowercase a, diæresis / umlaut
å | &#229; | &aring; | Lowercase a, ring
æ | &#230; | &aelig; | Lowercase ae ligature
ç | &#231; | &ccedil; | Lowercase c, cedilla
è | &#232; | &egrave; | Lowercase e, grave accent
é | &#233; | &eacute; | Lowercase e, acute accent
ê | &#234; | &ecirc; | Lowercase e, circumflex
ë | &#235; | &euml; | Lowercase e, diæresis / umlaut
ì | &#236; | &igrave; | Lowercase i, grave accent
í | &#237; | &iacute; | Lowercase i, acute accent
î | &#238; | &icirc; | Lowercase i, circumflex
ï | &#239; | &iuml; | Lowercase i, diæresis / umlaut
ð | &#240; | &eth; | Lowercase eth, Icelandic
ñ | &#241; | &ntilde; | Lowercase n, tilde
ò | &#242; | &ograve; | Lowercase o, grave accent
ó | &#243; | &oacute; | Lowercase o, acute accent
ô | &#244; | &ocirc; | Lowercase o, circumflex
õ | &#245; | &otilde; | Lowercase o, tilde
ö | &#246; | &ouml; | Lowercase o, diæresis / umlaut
÷ &#247; &divide; Division sign
ø | &#248; | &oslash; | Lowercase o, slash
ù | &#249; | &ugrave; | Lowercase u, grave accent
ú | &#250; | &uacute; | Lowercase u, acute accent
û | &#251; | &ucirc; | Lowercase u, circumflex
ü | &#252; | &uuml; | Lowercase u, diæresis / umlaut
ý | &#253; | &yacute; | Lowercase y, acute accent
þ | &#254; | &thorn; | Lowercase thorn, Icelandic
ÿ | &#255; | &yuml; | Lowercase y, diæresis / umlaut


About the Authors

Eric Schurman
Eric is currently a development lead at Microsoft, where he oversees the development of two large external Web sites. He has also worked on computer-based training programs and back-end tools for managing and creating Web-based content. He has held positions with the U. S. Department of State, the University of Washington, Aldus, Adobe Systems, and the Academy of Computer Technology in software development, technical support, training, and instructional design. Eric was born in Honolulu, Hawaii, and has traveled extensively. When time permits, he enjoys physical, outdoor sports, including mountain biking, snowboarding, and rollerblading. He graduated from the University of Washington in 1994, earning bachelor’s degrees in both Zoology and Psychology.

Bill Pardi
After completing a bachelor’s degree in broadcast production at Cedarville College in Ohio, Bill earned a master’s in Television/Radio/Film at Syracuse University. He decided on a career in multimedia software development after his first encounter with the subject in a course at Syracuse. Following his work as a developer on several multimedia reference titles with Multicom Publishing in Seattle, Bill accepted a position with Microsoft as a program manager. He is now lead program manager and works with a talented team of people creating interactive training software. Bill’s after-work activities include writing about technology and playing with his two boys. Originally from New York, he currently lives in Edgewood, Washington, with his wife Jodie and their two sons, Cody and Ryan.


About This Electronic Book

This electronic book was originally created—and still may be purchased—as a print book. For simplicity, the electronic version of this book has been modified as little as possible from its original form. For instance, there may be occasional references to sample files that come with the book. These files are available with the print version, but are not provided in this electronic edition.

“Expanding” Graphics

Many of the graphics shown in this book are quite large. To improve the readability of the book, reduced versions of these graphics are shown in the text. To see a full-size version, click on the reduced graphic.


About Microsoft Press

Your Information Source

Microsoft Press is a division of Microsoft Corporation and the leading source of comprehensive self-paced learning, training, evaluation, and support resources to help everyone from developers to IT professionals to end users get the most from Microsoft® technology. Choose from more than 250 current titles in print, multimedia, and network-ready formats—learning solutions made by Microsoft, with the most timely and accurate information available. For more information, visit http://mspress.microsoft.com/.


Figure 1-1

Figure 1-1. Text formatting in HTML.


Figure 1-2

Figure 1-2. Dynamic styles using Cascading Style Sheets.


Figure 2-1

Figure 2-1. A basic Web page.


Figure 2-2

Figure 2-2. A page with sample character formatting.


Figure 2-3

Figure 2-3. Formatting characters with the <FONT> tag.


Figure 2-4

Figure 2-4. A page containing line formatting tags.


Figure 2-6

Figure 2-6. A page showing various text alignments.


Figure 2-7

Figure 2-7. A page containing images and links.


Figure 2-8

Figure 2-8. An example of an unordered list.


Figure 2-9

Figure 2-9.An example of an ordered list.


Figure 2-10

Figure 2-10. An example of a complex list.


Figure 3-1

Figure 3-1. A basic table.


Figure 3-2

Figure 3-2. Two tables that illustrate basic table formatting.


Figure 3-3

Figure 3-3. A table illustrating the use of the COLSPAN attribute.


Figure 3-4

Figure 3-4. A table that illustrates the use of both the COLSPAN and ROWSPAN attributes.


Figure 3-5

Figure 3-5. An example of embedded tables.


Figure 3-6

Figure 3-6. An example of using a table for page layout.


Figure 3-7

Figure 3-7. Using the BORDER attribute to troubleshoot tables.


Figure 3-8

Figure 3-8. A basic frameset document.


Figure 3-9

Figure 3-9. A more advanced frameset.


Figure 3-10

Figure 3-10. A frameset with a navigation bar.


Figure 4-1

Figure 4-1. A basic form.


Figure 4-2

Figure 4-2. The various types of INPUT elements.


Figure 4-3

Figure 4-3. Use of the TEXTAREA element.


Figure 4-4

Figure 4-4. Creating drop-down lists.


Figure 4-5

Figure 4-5. Use of the different comment tags.


Figure 4-7

Figure 4-7. Users can click on the image to navigate.


Figure 4-8

Figure 4-8. Basic styles on SPAN and DIV elements.


Figure 4-9

Figure 4-9. The XMP tag exposes the underlying code.


Figure 4-10

Figure 4-10. Character entities display as their corresponding characters.


Figure 7-1

Figure 7-1. The dialog box indicates the width and the height of the image.


Figure 7-2

Figure 7-2. When the image changes, the dialog box indicates the new property values.


Figure 7-3

Figure 7-3. Initially, the Internet Explorer window looks like this; but as you move the mouse and click it, different events occur.


Figure 7-4

Figure 7-4. When you move the mouse over the text in the SPAN element, the onmouseover event is fired and the text changes.


Figure 7-5

Figure 7-5. When you move the mouse away from the text, the onmouseout event is fired and the text changes again.


Figure 7-6

Figure 7-6. In Internet Explorer, an Alert dialog box indicates that the IMG object was clicked.


Figure 7-7

Figure 7-7. In Internet Explorer, a different Alert dialog box is displayed when the text is clicked.


Figure 7-8

Figure 7-8. The contents of the Netscape Navigator window after the body of the document is clicked.


Figure 7-9

Figure 7-9. Clicking the image now generates this display rather than the one shown in Figure 7-6.


Figure 7-10

Figure 7-10. Clicking any one of these three buttons produces a dialog box.


Figure 7-11

Figure 7-11. An Alert dialog box.


Figure 7-12

Figure 7-12. A Prompt dialog box.


Figure 7-13

Figure 7-13. A Confirm dialog box.


Figure 7-14

Figure 7-14. The Internet Explorer window before any changes are made.


Figure 7-15

Figure 7-15. This Alert dialog box lists each page element and its index.


Figure 7-16

Figure 7-16. The all collection was just used to alter the item at index 6 (the second image). Next the third image will be changed.


Figure 7-17

Figure 7-17. The all collection is used with the tags method to alter the third image.


Figure 7-18

Figure 7-18. The images collection is used to alter the second image.


Figure 8-1

Figure 8-1. Displaying different data types.


Figure 8-2

Figure 8-2. Accessing the Object Model. Clicking the Display Value button displays the value of the text input.


Figure 8-3

Figure 8-3. Creating an object.


Figure 8-4

Figure 8-4. Using an array.


Figure 8-5

Figure 8-5. Using the + (addition or concatenation) operator.


Figure 8-6

Figure 8-6. Using the typeof operator.


Figure 8-7

Figure 8-7. Effects of converting one data type to another.


Figure 8-8

Figure 8-8. Using string methods.


Figure 8-9

Figure 8-9. Using the Math object.


Figure 9-1

Figure 9-1. An Alert dialog box appears after a button is clicked.


Figure 9-2

Figure 9-2. Retrieving a value from a function.


Figure 9-3

Figure 9-3. Checking data for errors.


Figure 9-4

Figure 9-4. Using a switch statement.


Figure 9-5

Figure 9-5. Information about the document object.


Figure 10-1

Figure 10-1. Several ways to debug.


Figure 10-2

Figure 10-2. A programmed error message appears…


Figure 10-3

Figure 10-3. ...and then an alternate image is loaded.


Figure 10-4

Figure 10-4. The error dialog from Internet Explorer when Code Listing 10-3 is run.


Figure 10-5

Figure 10-5. Code Listing 10-4 handles the error.


Figure 10-6

Figure 10-6. Code Listing 10-5 handles an error with a try...catch statement.


Figure 11-1

Figure 11-1. A simple HTML document without styles.


Figure 11-2

Figure 11-2. An example of applying an in-line style.


Figure 11-3

Figure 11-3. An example of using multiple in-line styles in the same tag.


Figure 11-4

Figure 11-4. An example of using a global style sheet.


Figure 11-5

Figure 11-5. Using a global style sheet that affects text in all SPAN elements.


Figure 11-6

Figure 11-6. Using a global style sheet to change the styles of multiple elements.


Figure 11-7

Figure 11-7. An example of an in-line style used to override a global style sheet.


Figure 11-8

Figure 11-8. Sample text styled with a linked style sheet.


Figure 11-9

Figure 11-9. An example of a nested element.


Figure 11-10

Figure 11-10. An example of style inheritance.


Figure 11-11

Figure 11-11. Only the font size is changed by the B classes.


Figure 11-12

Figure 11-12. All types of elements can be affected by a global class.


Figure 11-13

Figure 11-13. A link is highlighted and underlined when the mouse goes over it.


Figure 12-1

Figure 12-1. Some CSS formatting in Internet Explorer.


Figure 12-2

Figure 12-2. The same page in Navigator 4.08.


Figure 12-3

Figure 12-3. An example of using CSS attributes to affect fonts.


Figure 12-4

Figure 12-4. An example of using CSS attributes to format text.


Figure 12-5

Figure 12-5. This Web page specifies three fonts that are not available on the target machine.


Figure 12-6

Figure 12-6. Embedded fonts display the text as intended.


Figure 13-1

Figure 13-1. You can use the background-color attribute to change the color that appears behind an element.


Figure 13-2

Figure 13-2. You can use the background-image attribute to display an image behind an element.


Figure 13-3

Figure 13-3. You can use the background-repeat attribute to repeat a background image in various ways.


Figure 13-4

Figure 13-4. You can use the background-position attribute to control where the background image is placed.


Figure 13-5

Figure 13-5. With the border-width attribute, you can vary the widths of borders.


Figure 13-6

Figure 13-6. You can change the style of a border with the border-style attribute.


Figure 13-7

Figure 13-7. You can use the border shorthand property to set the width, style, and color of an entire border at one time.


Figure 13-8

Figure 13-8. Each side of this element has a different border.


Figure 13-9

Figure 13-9. The padding and margin attributes control the spacing around an element.


Figure 13-10

Figure 13-10. Using the position, top, and left attributes to position elements on a page.


Figure 13-11

Figure 13-11. You can use the z-index attribute to place elements in front of or behind other elements.


Figure 13-12

Figure 13-12. The display and visibility attributes let you control whether an element is displayed on your page.


Figure 13-13

Figure 13-13. The overflow attribute controls how a constrained-size element is displayed on your page.


Figure 13-14

Figure 13-14. The clip attribute lets you crop an object to a particular size.


Figure 14-1

Figure 14-1. Using border-collapse to collapse a table's border.


Figure 14-2

Figure 14-2. Using a table-layout of fixed to control the layout of a table.


Figure 14-3

Figure 14-3. The cursor CSS attribute controls the display of the mouse pointer.


Figure 14-4

Figure 14-4. The CSS attributes page-break-before and page-break-after affect the appearance of the printout, not the displayed page.


Figure 14-5

Figure 14-5. You can control the list marker by using the list-style-type CSS attribute.


Figure 14-6

Figure 14-6. The list-style-image attribute sets an image as an item marker, and the list-style-position attribute controls text wrap.


Figure 15-1

Figure 15-1. The initial display before the MySpan element is clicked.


Figure 15-2

Figure 15-2. The first Alert dialog box.


Figure 15-3

Figure 15-3. The second Alert dialog box.


Figure 15-4

Figure 15-4. The final display after the font weight is changed.


Figure 15-5

Figure 15-5. The initial outline, in collapsed form.


Figure 15-6

Figure 15-6. The outline dynamically expands when the user clicks Section 2.


Figure 15-7

Figure 15-7. The initial outline, using the visibility property.


Figure 15-8

Figure 15-8. The outline is dynamically filled in when the user clicks Section 2.


Figure 15-9

Figure 15-9. The Web page before the user moves the mouse.


Figure 15-10

Figure 15-10. One possible example of a Web page after the user moves the mouse.


Figure 16-1

Figure 16-1. Applying the blur filter to an object.


Figure 16-2

Figure 16-2. Other available visual filters.


Figure 16-3

Figure 16-3. Applying filters dynamically through script.


Figure 16-4

Figure 16-4. Applying multiple filters to an object.


Figure 16-5

Figure 16-5. Partway through the transition of the image into visibility.


Figure 16-7

Figure 16-7. A combination of the random dissolve and circle out transition effects with the shadow filter.


Figure 17-1

Figure 17-1. A sound control panel in Internet Explorer.


Figure 17-2

Figure 17-2. The same content in Netscape Navigator 4.


Figure 17-3

Figure 17-3. A video control panel in Internet Explorer.


Figure 17-4

Figure 17-4. The same content in Netscape Navigator 4 after the video is started.


Figure 17-5

Figure 17-5. This technique plays the video in an external window.


Figure 17-6

Figure 17-6. This technique plays embedded video or starts an external window.


Figure 17-7

Figure 17-7. A still shot of an animated GIF.


Figure 18-1

Figure 18-1. An <IMG> tag that uses the DYNSRC attribute.


Figure 18-2

Figure 18-2. A basic use of the Media Player control.


Figure 18-3

Figure 18-3. Using script to change a control's properties.


Figure 18-4

Figure 18-4. A warning is displayed to the user if sound is not available.


Figure 18-5

Figure 18-5. You can control sound layers with input buttons and script.


Figure 19-2

Figure 19-2. This entire page, including the graphics code, is only 2.67 KB.


Figure 19-3

Figure 19-3. The graphic can be rotated around any axis.


Figure 19-5

Figure 19-5. The sprite of the Earth can be manipulated with the on screen buttons.


Figure 19-6

Figure 19-6. Using the Sprite control to enable users to manipulate an image.


Figure 20-2

Figure 20-2. All columns of the record are displayed, and controls that let you move through and examine the data are added.


Figure 20-3

Figure 20-3. A table of data constructed without using data binding.


Figure 20-4

Figure 20-4 A table of data constructed with data binding.


Figure 20-5

Figure 20-5. The same set of records after being sorted and filtered.


Figure 21-3

Figure 21-3. Displaying the XML document content.


Figure 22-1

Figure 22-1. The button created on the second page allows the public function to be called from outside the scriptlet.


Figure 22-2

Figure 22-2. The menu before a heading is clicked.


Figure 22-3

Figure 22-3. Code Listing 22-4 displays fully opened in Netscape Navigator.


Figure 22-4

Figure 22-4. The menu after Level 1 Item 1 is clicked.


Figure 22-6

Figure 22-6. This page saves and retrieves information in cookies. This screen shows what happens when the Display button is clicked after two new cookies have been created.


Figure 22-9

Figure 22-9.The channel logo is displayed in the Internet Explorer Channels Folder.


Figure 22-10

Figure 22-10. The Internet Explorer Content Advisor allows users to restrict access to objectionable content.


Figure 23-1

Figure 23-1. Each of the buttons uses a different function to display the value of the selected item.


Figure 23-2

Figure 23-2. Some of the properties of the navigator object in Internet Explorer 5.


Figure 23-3

Figure 23-3. The same page in Netscape Navigator 4.08.


Figure 23-4

Figure 23-4. This page writes a different style sheet in each browser.


Figure 23-5

Figure 23-5. This page displays a number of different system settings.


Figure 24-1

Figure 24-1. The home page for our Web site.


Figure 24-2

Figure 24-2. This page allows customization by the user.


Appendix A-1

Figure A-1. The two tables behave differently as the mouse movements interact with them.


Appendix A-2

Figure A-2. The second image uses transparent areas around the letters.