Vous êtes sur la page 1sur 1288

Mister Hack

Special Edition Using Visual Basic Script

Special Edition Using JScript

YO!

Special Edition Using Visual Basic Script


by Ron Schwarz and Ibrahim Malluf

Copyright, Credits, Acknowledgements, Dedication, About the Authors, We'd like to Hear From You

Introduction Part I - Microsoft, the Internet, and You


q q q

Chapter 1 VBScript and the World Wide Web Chapter 2 Review of HTML Chapter 3 Introducing the ActiveX Control Pad

Part II - Visual Basic Scripting Edition: Active Intelligence for Internet Browsers
q q q q q q q

Chapter 4 Creating a Standard HTML Page Chapter 5 Internet Explorer Chapter 6 Creating an HTML Layout Page Chapter 7 ActiveX Objects Chapter 8 Security Chapter 9 An Introduction to Distributed Objects Chapter 10 Embedding Internet Explorer into Your Application

Part III - VBScript Programming Overiew


q q

Chapter 11 Designing VBScript Applications Chapter 12 A Simple VBScript Page

q q

Chapter 13 Comparing VBScript, VBA, and Visual Basic Chapter 14 Comparing Scripting Languages

Part IV - Doing Real Work with VBScript


q q q q q q

Chapter 15 VBScript Data Types and Variables Chapter 16 VBScript Operators Chapter 17 VBScript Control of Flow and Error Handling Chapter 18 VBScript Event Programming Chapter 19 VBScript Procedures Chapter 20 VBScript Forms, Controls, and Managing Transactions

Part V - Advanced Techniques, Tactics, and Pitfalls


q q q q

Chapter 21 Accessing Data Chapter 22 VBScript Language Elements Chapter 23 Microsoft SQL Server Web Extensions Chapter 24 Building Internet Rating Applications

Part VI - Appendixes
q q q q

Appendix A History of the Internet Appendix B HTML Reference Appendix C VBScript Coding Conventions Appendix D Porting Visual Basic Applications

| Book Home Page | Buy This Book | | Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

Special Edition Using VBScript


by Ron Schwarz and Ibrahim Malluf with William Beem Yusuf Malluf Michael Marchuk Tom Tessier

Special Edition Using VBScript


Copyright 1996 by Quetm Corporation. All rights reserved. Printed in the United States of America. No part of this book may be used or reproduced in any form or by any means, or stored in a database or retrieval system, without prior written permission of the publisher except in the case of brief quotations embodied in critical articles and reviews. Making copies of any part of this book for any purpose other than your own personal use is a violation of United States copyright laws. For information, address Que Corporation, 201 W. 103rd Street, Indianapolis, IN, 46290. You may reach Que's direct sales line by calling 1-800-4285331. Library of Congress Catalog No.: 96-68981 ISBN: 0-7897-0809-4 This book is sold as is, without warranty of any kind, either express or implied, respecting the contents of this book, including but not limited to implied warranties for the book's quality, performance, merchantability, or fitness for any particular purpose. Neither Que Corporation nor its dealers or distributors shall be liable to the purchaser or any other person or entity with respect to any liability, loss, or damage caused or alleged to have been caused directly or indirectly by this book.

All terms mentioned in this book that are known to be trademarks or service marks have been appropriately capitalized. Que cannot attest to the accuracy of this information. Use of a term in this book should not be regarded as affecting the validity of any trademark or service mark. Screen reproductions in this book were created using Collage Plus from Inner Media, Inc., Hollis, NH.

Credits
President Roland Elgey Publisher Joseph B. Wikert Editorial Services Director Elizabeth Keaffaber Managing Editor Sandy Doell Director of Marketing Lynn E. Zingraf Publishing Manager Bryan Gambrel Acquisitions Editor Angela C. Kozlowski Product Director Russ Jacobs Production Editor

Susan Ross Moore Editors Kelli M. Brooks Kate Givens Sydney Jones Patrick Kanouse Jeanne Terheide Lemen Midge Stocker Product Marketing Manager Kim Margolius Assistant Product Marketing Manager Christy M. Miller Technical Editor Brendan Mirotchnick Tim Schuback Acquisitions Coordinator Carmen Krikorian Software Relations Coordinator Patricia J. Brooks Editorial Assistant Andrea Duvall Electronic Book Version Kevin Blocher

Dedication
This book is dedicated to Susan Yeager, whose love and support saw me through many trying times during its creation. Ron Schwarz

Subhanna Hu'a Ta Allah Ibrahim Malluf

About the Authors


Ron Schwarz is a software developer in Mt. Pleasant, Michigan. He has written the CD Tutor presentation program used in Que's Delphi 2 Tutor (featured in August '96 issue of Visual Basic Programmer's Journal "Basic Heroes" column), and is currently writing a Que book covering a future version of Visual Basic. He wrote Performance Track (A web chart creation and management system, used in the automotive industry and education), and Launch Control, (a DOS and Windows shell). He has been involved in software development since the late 1970s, and has worked with Visual Basic since version 1.0 was released. His programming philosophy is based on the idea that ease of use and power are not mutually exclusive concepts. His WWW home page is available at http://www.nethawk.com/~rs, and his e-mail address is ron.schwarz@nethawk.com. Ibrahim Malluf (Malluf Consulting Services 505-832-6187) is a Systems Consultant to a variety of industries. He is the principle partner and founder of CyberLex Software that produces multimedia CD catalogs for industry. His primary focus is on Relational Database development and MS Office/ Back Office solutions that include the Internet/intranet. He is also a Microsoft MVP, Section Leader of the Visual Basic Programmer's Journal's Science & Industrial section Compuserve forum, the sysop of the VBScript Development and Intranet Development forum's on the Developer's Exchange (http:\\www.windx.com) and writes a regular VBScript column for Avatar Magazine (http:\\www. avatarmag.com). He also is a founding member of the Albuquerque Visual Basic Users Group. During his spare time (yeah right!) he sleeps. He can be reached at iymalluf@rt66.com

Acknowledgments
I'd like to thank the many kind folks at Que, including my editors on this project (Angela Kozlowski

and Steve Miller) who went the extra mile when dealing with the rapidly-changing VBS/Internet situation. Finally, I thank my friend and co-author Ibrahim Malluf, who has been a constant source of inspiration and knowledge. Ron Schwarz

Where do I begin? Let me start out with Angela Kozlowski who must have felt that the production of this book was a plot to drive her insane. Every time she thought she had a handle on it, Ron and I would be calling to tell her that things have changed again. Thank you Angela for the always-pleasant patience. Ron, my co-author on this book, is a close friend. We traveled together up and down on the ever-changing face of Visual Basic Script during one of the wildest betas I've ever been on. This book would not have been completed without his persistant drive to keep it going. The editing staff, led by Susan Moore, were faced with working on text that changed even as they were editing it. They also had to put up with two tired and cranky old men (me & Ron) who acted like they believed the editorial staff of Que was a plot to drive authors insane. They did a wonderful job. Then there is my wife, Jameela. I am almost certain that she had something to do with the food that would miraculously appear at the right corner of my desk and the constant flow of coffee into the wee hours of the night. Those men and women who are married to programming fanatics are the most patient and angelic people on earth. Jameela had an extra ounce of patience because along with her husband, she also had to put up with her 17 year old son who was also writing chapters for this book. She had to act as referee between the both of us when we disagreed or contradicted each other on the finer points of HTML or Visual Basic Script. This was in addition to the normal ego conflicts between a father and his teenage son. Speaking of Yusuf (my son), with all of the horror stories you read about in the paper or see on TV about teenage violence and crime, I have to count myself among the most fortunate people on Earth. (Yes, I'm bragging.) At seventeen, he has developed a personal responsibility that far surpases his age and has been a tremendous asset to this book. For all of these people that have added much to the quality of this experience and to my life, I give thanks to Allah. Ibrahim Malluf on a Beautiful Monday Morning, August 5, 1996

We'd Like to Hear from You!


As part of our continuing effort to produce books of the highest possible quality, Que would like to hear your comments. To stay competitive, we really want you, as a computer book reader and user, to let us know what you like or dislike most about this book or other Que products. You can mail comments, ideas, or suggestions for improving future editions to the address below, or send us a fax at (317) 581-4663. For the online inclined, Macmillan Computer Publishing has a forum on CompuServe (type GO QUEBOOKS at any prompt) through which our staff and authors are available for questions and comments. The address of our Internet site is http://www.mcp.com

(World Wide Web). In addition to exploring our forum, please feel free to contact me personally to discuss your opinions of this book: I'm 75703,3504 on CompuServe, and I'm akozlowski@que.mcp.com on the Internet. Thanks in advance--your comments will help us to continue publishing the best books available on computer topics in today's market. Angela C. Kozlowski Acquisitions Editor Que Corporation 201 W. 103rd Street Indianapolis, Indiana 46290 USA

| Table of Contents | Book Home Page | Buy This Book |


| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

Introduction

As this book is being written, the Internet is in a tremendous state of flux. It's likely this constant transformation will continue for at least the next few months, as Microsoft continues to bombard us with more and more fantastic tools and protocols. While this hectic rate of change makes for a wild ride, it's good to keep the ultimate goal in mind: a limitless vista of programming opportunity, balanced by a set of development tools of unprecedented power, flexibility, and ease of use. This book is constructed of five sections that provide a logical framework for learning to get around in this new realm. The first three parts provide a foundation to enable you to learning VBScript indepth. Part 1, "Microsoft, The Internet, and You," is an overview of where the Internet is today, where it's headed, and how the you'll be able to capitalize on it using VBScript. Part 2, "Visual Basic Scripting Edition: Active Intelligence for Internet Browsers," is a group of chapters demonstrating the types of solutions that lend themselves to VBScript programming, and a glimpse into the types of things that can be done. Part 3, "VBScript Programming Overview," reveals the essentials of VBScripthow scripts are created, and the nitty-gritty of melding them to Web pages, mixing with HTML elements, using the VB language as implemented in VBScript, and how it differs from "full" Visual Basic. Part 4, "Doing Real Work with VBScript," is where you'll dig in and learn the nitty-gritty details. Part 5, "Advanced Techniques, Tactics, and Pitfalls," recognizes that VBScript, due to the environment in which it's used, is fraught with subtlety. At times, it can be maddening, as the authors of this book can readily attest. Part 5 steers you around some of the craters and help you get the skills to find others on your own. It also covers several advanced topics, such as sending information to and from the server and VRML 3D. Finally, a series of appendixes will help fill in the gaps, by providing a brief history of the Internet, references to HTML, VBScript coding conventions, and tips on porting VB applications over to VBScript. Writing this book has been a real adventure. In addition to the Internet being in a state of flux, we've had to wrestle with a series of early release versions of the Internet Explorer 3.0, VBScript, and the ActiveX Layout Pad. We watched in horror as the specifications changedrepeatedlybefore our eyes. The language evolved as we documented it; we spent at least as much time staying on top of

changes, and rewriting what we'd already written, as we did writing the original manuscript. As we thought we were nearing completion of the book, Microsoft quietly dropped a bombshell, without any advance warning. The sudden, unexpected appearance of the ActiveX Control Pad, with its accompanying HTML Layout Page control, completely changed everythingnot only for us but for you, too, as well as anyone using the Web. Suddenly, we had a tool that would allow the creation of real programs in the context of a browser, with precise, completely discretionary placement and sizing of controls at any position on a form. We expect the new Layout Page features to virtually obsolete "traditional" HTML very quickly. A great many of the convoluted and arcane (and voluminous) details of HTML syntax have evolved as workaroundspeople wanted to create pages that looked the way they wanted them to look, but HTML wanted to take a stream of text and flow it in from the upper left to the lower right. From that conflict arose scads of HTML "features." Now, with the ActiveX Control Pad, anything can be placed anywhere, in any shape, size, or format, with nothing more than a few mouse clicks. And, it does it all without generating miles of underlying HTML; the new syntax is truly elegant. So, where are things headed from here? Here's what one Microsoft developer stated on their public newsgroup: "Nashville" has been a code name for the set of technologies that integrate the Windows shell with Internet Explorer. We're currently planning to do an "Internet Explorer 4.0" release that includes these technologies -- ie, integrates internet browsing with the shell -- and it will be free. That's rightthe Internet and the desktop will merge; you'll be able to browse files on your local machine, on your local network (in other words, "intranet"), and on the Internet, with total transparency. Not only that, but the document-centric philosophy will be taken to new heights, as applications end up performing more as operating system extensions than as stand-alone programs. Things are changing. You're in the midst of change, and we hope that what we've written in this book will help you navigate the changes, and succeed.

| Previous Chapter | Next Chapter |

| Table of Contents | Book Home Page | Buy This Book |


| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

Chapter 1 - VBScript and the World Wide Web


by Ron Schwarz

In this chapter
q q q q

q q

Where the Internet is today It's everywhere, and it's more than any one person can grasp. Learn where to focus, and how. What Microsoft is doing on the net An abundance of powerful tools and capabilities are being released, many of them free for the downloading. Learn what they are, and how they fit into the big picture. Where you fit in The changes occurring on the net bode well for programmers, especially VB programmers. Find out what some of the opportunities are, and how to implement them.

This chapter provides an overview of where weVBS programmersfit into the scheme of things vis-a-vis the Internet, and where it's all headed. The Internet continues to grow like Topsy, and it's easy to get overwhelmed. After a look at the plethora of "stuff" coming down the pike in everincreasing volume and speed, it's tempting to suggest Poe's "A Descent into the Maelstrom" as background material. Instead, we'll try to examine the big picture, separate the wheat from the chaff, and by so doing be able to have an advantage over others who choose to simply dive in, blindly hoping for the best.

Globalizing Information
What began as a nuclear-hardened network of military computers (see Appendix A, "History of the Internet") has overnight become the most prominent aspect of personal computing. The Internet is on the brink of fulfilling the promises the past two decades of desktop computing. What we thought the CD-ROM and online services would eventually bring, is now available to anyone with an inexpensive computer and modem, at a fraction of the cost. Within the next few years, Internet access is expected to be as universal as telephone and television access is today. Right now, traditional media, such as telephone, cable TV, and major broadcast

outfits, as well as software companies like Microsoft are in the process of developing the software, delivery and access systems, and content that will be used for the "set-top boxes" that are being planned. No one can say exactly when, or how it will all shape up, but one thing is clear: it will happen. And, when it happens, one key ingredient will be active content. And tools like VBScript will be what empowers it.

In the Land of the Blind, the One-Eyed Man is King


In the old days, it was easy to know nearly everything about any particular aspect of programming. Now, it sometimes seems amazing that anyone knows anything at all. Hardly a week passes that we are not inundated with new, powerful, and complex resources and tools. By the time you learn a task, it's been superseded; users, developers, and publishers are swamped by the increasing pace of growth in this field. In the old hierarchical model, you were either a specialist, or a generalist. Generalists filtered up to management, administration, and design positions, and specialists did the dirty work in the trenches. When the right mix of people and personalities were combined, things worked. Success now, however, requires a new model. You need to be a jack of most trades and master of some. You need a lot of broad knowledge about quite a few things, and, you need some stronglyfocused, in-depth expertise in some key subjects. The trick is to decide which ones to learn, which ones to master, and which ones to ignore. This book will try to guide you through that processat least so far as interactive web page development using VBScript is concernedand leave you with the resources to continue riding the wave. As software development matures, only the savvy will succeed. And as the wealth of new technologies continues to increase in volume, "savvyness" will become a scarce commodity. This is the time to stake your claim, and the way you'll do that is by learning how to learn, and what to learn. When you've done that, you'll be nicely positioned for what's just starting to happen now. The Internet is a global network of networks, overflowing with a mix of information ranging from the indispensable to the trite to the obscene. "The Internet" is not a company. You can't "contact the management" to deal with problems or provide solutions, because in a very real sense, there isn't any "management". Each system on the Internet, whether it's a large corporate network, or a kid with a net link in his parents' basement, has its own administration, with corresponding degrees of ability and accountability. There is no "central authority". The net has become a seething ocean of information and noise, and it's becoming increasingly difficult to find and use what's needed.

Chaos Brings Opportunity


The Internet holds an embarrassment of riches, to the extent that large numbers of users have become information junkies, while others burn out on information overload. Just as Microsoft Windows applications provide the ability to control more information by highly abstracting the interface, the vast resources of the Internet will also need to be effectively harnessed. We won't be able to get by with more toolswhat we need are better tools. You may not need power steering on a two-seat sportscar, but you'd find it essential if you're controlling massive earth-moving, logging, or mining

equipment. You need a way to leverage your time, effort, and knowledge, proportionate to the quantity of raw material you're managing.

The Web in the Window Windows-based applications don't provide their power and ease of use by means of linear-increase in functionality over their earlier non-GUI-based predecessors. Instead, they offer a higher degree of management and control by virtue of providing newer ways of doing things. Certainly, part of the process does consist of making existing tasks easier. Instead of having to learn numerous commands, control-keys, function keys, and layer after layer of text menus, the user can work with pulldown menus, toolbars, context menus, checkboxes, and other elements of modern GUI interface design. Time and effort previously wasted dealing with the mechanics of the task (and endless rote memorization of command sequences) can now be devoted to the work at hand. And, fewer distractions and lower stress levels lead to more efficient, effective, and contented users. As impressive as these improvements may be, the real power lies in features such as OLE automation, in-place activation, linked and embedded applications, compound documents, and doc objects, which make it possible to do things that were hitherto impossible. And what is the focus of these "things"? They provide a higher level of abstraction (and by implication, control) over content. They provide leverage. The basic interface elements aid productivity; they allow users to do the same things differently. OLE and related functionality leapfrog this, however, and provide the ability to multiply the effectiveness of the user, to the point that work that used to require days of effort by a team of experts can now be done in hours, (or minutes) by one person reasonably proficient in the use of a set of tools. Developing for Windows requires a different philosophy than developing for earlier non-GUI platforms. To succeed, you must learn to think differently. This same philosophy is mandatory if effective Internet development is to be anything beyond a pipe dream. "More" knowledge just can't cut it. There's just too much to learn. The most important action is focus, and the most important process is determining what to focus on. Learn how to learn, then learn what to learn. Then amaze everyone with your incredible insights!

The greatest area of growth in Internet use has been occurring with the World Wide Web. To many, if not most recent users, the WWW is "the net." (Thankfully, such awkward neologisms as "The

Information Superhighway" are dying a merciful and rapid death.) While the majority of users can safely exhibit this level of naivet, we as developers are afforded no such luxury. "The Web" is but one facet of the Internet; however, its prominence is not unwarranted, and as more and more traffic, as well as more kinds of traffic are carried, it's only natural to expect expanded capabilities and tools to appear. The current high level of chaos is a result of the volume of information, the sheer numbers of users, and the diversity of tools used to manage and access the web. Whoever brings order out of chaos will stand to directly benefit. This is a good time to know Visual Basic, and a good time to be writing code. You've probably heard the phrase "Active Content." While it covers a lot of territory, the most important things to keep in mind right now are that it's real, it's probably the most significant new factor in Internet programming, and VBScript falls smack dab in the middle of it all. If you're coming from a traditional HTML programming background, you'll find exciting new possibilities for interactive web pages. If you're a long time VB hack, you'll be able to quickly put your skills to work.

The Internet, and Intranets


Just when the world is learning what the Internet is, along comes another buzzword: "Intranets." Essentially, Intranets are kid brothers to the Internet, and present exciting new opportunities for developers. What the Internet is to the world, Intranets are to organizations. Although different types of content are generally involved, methodologies are identical, and the benefits are significant

Intranet are is more than a buzzword for network or LAN. An intranet is a type of LAN, the significant point being the fact that intranets use Internet style tools and applications to manage and present content.

One key element of Intranets is exclusivity. Whereas the Internet is an open, global network, Intranets are proprietary to the organizations that create and administer them. This opens a world of exciting development opportunities, as each organization's needs are different.

The World on the Desktop


The next generation of Windows will provide seamless integration of the Internet and your local computer. The Windows Explorer will provide access to the Internet, and, access to other machines in an organization's Intranet, too. Documents will be accessible the same way whether they are on your local hard drive, on another machine in your local network, or anywhere in the world on the Internet. All this will be accomplished using the same metaphorno longer will users have to learn

three different ways of working. As Intranets proliferate and supersede traditional networking approaches, a "grand unification" of sorts will occurwhere information is located will essentially cease to be an issue; instead, users can concentrate on what they need to do with it. Users can focus on tasks, letting the system deal with processes.

A Fractal Microcosm
To get an idea of what an Intranet is, take a look at the Internet, then view it in the context of your naval meditating on you. It's a bit counterintuitive at first, if not downright retrograde. What the Internet is to the world, an Intranet is to your local organization. In a sense, it's a miniature walled-off alternate universe clone of the Internet. So what's the big deal anyway? The same productivity and comfort payoffs that the Internet provides for global information are available locally with an Intranet. In fact, the same tools are used, and the same skills are used. While many people perceive LAN applications to be stagnant, difficult to learn, painful to use, and downright obtuse, Internet software has become incredibly powerful, and (from the users' perspective, at least) extremely easy to learn, and use. Probably the main reason for this is simple economics of scale. The very large base of Internet users has created an attractive target for application developers. The result of all this is a proliferation of "mini-Internets" (quickly termed Intranets), which breathe new life into LAN technology, and, create a burgeoning new market for application developers. And, as new tools like VBScript make it easy to create web pages that move beyond the realm of "virtual television", whole new markets will quickly appear. Corporate information systems will no longer be limited to whatever access an overworked "priesthood" can provide. Support staff will have be able to get information they need, when they need it, without having to tackle any learning curves other than that required for basic operation of Windows.

The Microsoft Vision: Information at your Fingertips


As large corporations go, Microsoft is unique. Generally, the rule is that the bigger they are, the slower they move, and the more inertia-bound they become, until they reach a point at which they are overtaken by a team of garage operators with that lean and hungry look. 'Taint so in Redmond. The folks there have learned how to be big, and how to be nimble at the same time. They rigorously apply a set of principles that ensure steady, continuous progress, and real growth. Fortunately, there's no big secret involved herethe rules are pretty straightforward, as we'll see, and we can apply them with similar results (albeit on a less-grandiose scale) to our own operations.

Broken Paradoxes

Microsoft is not perfect. They make mistakes. They head off in wrong directions, they make strategic blunders, and they develop software that people don't use or like. In that regard, they're just like everyone else. However, Microsoft learns from its mistakes. You won't see them make the same mistake twice. Other companies seem to run into the same brick walls over and over again, as if mindless repetition has some merit in and of itself. While the largest corporations may have the resources (by virtue of sheer mass, if nothing else) to survive such pigheadedness for a while, countless smaller outfits wash in and out with the tides. Microsoft, in spite of all this, has become the de-facto leader in their field, and only the sour-grapes crowd seriously attributes it to their size. The fact is, they are darn good at what they do, and a great deal of what they do consists of analyzing where things are headed. So, even though they are subject to the same limitations as any other group of people working in this industry, they manage to make steady progress. They work hard, and they work smart. And when they commit to something with the fervor they've dedicated to the Internet, you should ignore them at your own peril.

Having it All, and Using it All


The tools are available. The market is available. After you read this book, you'll have the skills required. What's missing? Direction. Without a vision of where you fit in to the scheme of things, you'll be like someone at the airport, bags packed, ready to go, but with no destination. You can bet that a lot of your competition will simply try to reinvent the wheel, only on a grander scale. Let's face it: what separates a great programmer from a competent programmer is not so much coding skills as much as it is the ability to think. Too many programmers spend too much time writing code, and too little time thinking about what they are writing. The inclination, of course, is to subconsciously view time spent thinking as time wasted, since nothing tangible results from it. Nothing could be further from the truth. Diving in before you have a clear idea of where you're going is simply one more variation on the "haste makes waste" theme. When you're running around in circles, shifting into high gear does not translate into progress. Time spent reading, studying, learning, and above all, thinking, is anything but wasted. Just as we should not be afraid to learn from the failures of others, we ought to take a look at their successes, too. Microsoft is a prime exampleit's clear from the breadth and depth of their present Internet offerings that a fantastic amount of thought and planning has gone into the process. We can benefit from this in two ways. First, we can ride their coattails. The less industrious will merely grab the latest tools, and hope that this alone will be sufficient to keep them in business. The rest of us, however, will want to take the time and effort to determine where Microsoft is headed, and

anticipate how we can fit into things. Granted, they (understandably) play things close to the vest it's not in their interest to tip their hand to the competition. Even so, there's more than enough solid info available in press releases, online notes, SDK documentation, published interviews, and books like this, to give us what we need to get an idea of what's going on. Keeping an ear to the ground is a good way to avoid the plight of buggy-whip manufacturers in Henry Ford's time. The second way we stand to gain from this is by emulating their methods. Study, think, plan, test, and review. Above all, review your failures. When something goes wrong, find out what went wrong, why it went wrong, and how to avoid it in the future. Too many developers focus on their successes, but quickly distance themselves from their failures. Never underestimate the value of an intensive post-mortem.

Looking Over the Next Hill One lesson American corporations are finally learning from the Japanese is the false economy of short-sighted planning. While we were basing long-term decisions on quarterly payoffs, they were willing to accept short-term losses as part of long-term strategy. It's really nothing more than avoiding missing the forest for the trees. When you're driving your car, you know to "drive long," and watch the road more than one car-length ahead. It's the same when writing software, and this becomes even more of a consideration when beginning to use a new environment, such as VBScript.

To be sure, you will be applying many of your existing skills. But, whether you're coming from an HTML background, or a VB background, you're going to have to learn to think differently. You don't want to be one more wheel-reinventor, right? For a while now, a type of web interactivity has existed. We've all seen sites that allow searches, selection of options, and fill-in-the-blanks form entry. Of course, it's been fairly crude, since all the logic was contained at the server end, and was further restricted by CGI limitations. So, you can expect to see a proliferation of VBScript pages that are little more than direct translations of older CGI style interactive pages, with perhaps a few cosmetic bells and whistles tacked on, reminiscent of the "ransom note" effectmixed fonts, sizes, and styles, all on the same pagethat earmarked the initial efforts of neophytes when desktop publishing software became widely available. This same type of thinking (or more correctly, lack of thought) thwarted the efforts of numerous DOS programmers when they made the initial transition to Windows programming. Direct "translations" of old-style applications to the new environment were common. New platforms require new ways of thinking. Those who are the first to realize this, and the first to

learn the new ways, will be the ones who position themselves to benefit the most from the technology. Those who persist in trying to do new things using old methods will be doomed to years of hard work for little return. We're entering an era where pretty much everything will be new to everyone. Yes, it's a bit intimidating. But it's also rife with opportunity. After all, when everyone is at the starting gate at the same time, we all have an equal chance of success. Bill Gates got his start as a teenager by writing the first decent BASIC interpreter for 8-bit microcomputers. He didn't have much of an advantage over his contemporaries, other than the foresight to take the available resources, and be the first to use them to that end. Opportunities like this don't come along very often, and the astute reader will realize this, and capitalize on it. So, we've decided that we have the tools we need, we are dedicated to using them thoughtfully, and we are going to be anything other than one more me-too hack slaving away at painfully tedious work. After all, we want to excel at what we're doing, but we want to enjoy our work too! So, what to do? The first step is to look at what's being done now without tools like VBScript. (If you don't want to intentionally reinvent the wheel, you certainly don't want to inadvertently do so!) Examine different web sites that offer old-style HTML interactivity. (Remember to do your testing on systems that are connected to the Internet via modem linksif you're using a super-fast direct connection, you will not get a feeling for the frustration the vast majority of users face when using server-bound HTML interactivity.) Pay attention to look and feel, capabilities, and limitations. Pay particular attention to things that are slow, cumbersome, and awkward. Ask yourself if the things you don't like are due to programmer failings, or reflect basic shortcomings of the HTML-way of doing things. At this point, the immediate temptation will be to think of ways to work around these problems with VBScript. As with most temptations, though, the rewards are largely illusory. Remember, we're out to avoid reinventing the wheel. The reason we're examining the way things are done now is not so that we can do the same things, only better. Instead, we want to familiarize ourselves with the limitations inherent in the current platform, and use the new technology to leapfrog the competition. By realizing the restrictions built-into the current HTML world, we can begin to see to what extent look-and-feel is shaped by the environment in which it exists. By making a "gripe list" of things we don't like, we can get a sense of just how low the ceiling is. Eventually, we'll form an instinctive disgust for the innate restrictions of HTML, and lose any and all interest in emulating them. When you reach that point, you'll be chomping at the bit to see what VBScript can do for you, and your users. And, you'll have zero inclination to reinvent the wheel. The next step is to familiarize yourself with the tools. Learn what they are, how they interact, and how to use them. Find other people using the same tool sets, and form strategic alliances. (Cut-throat

competition may be fine for used-car sales, but chances are, you don't even have a tacky plaid suit...)

The Tools
VBScript is one part of Microsoft's Internet strategy. So are the Internet Explorer (IE), Internet Information Server (IIS), VRML, SQL Server 6.5, dbWeb, ActiveX SDK (and controls), the Internet Control Pack (ICP), FrontPage, Jakarta, Java, and on and on. The offerings are so extensive that it's impossible to pay more than lip service to them all in any one book. One thing to remember, though, is that Microsoft is literally the "House that Basic Built," and we can see that this versatile language is being given a place of prominence in the realm of Internet development.

Internet Explorer
In most cases (at least until other vendors get on the bandwagon and add VBScript compliance to their browsers), you, and your users will be using the Internet Explorer. The IE will be fully integrated into the next versions of Windows, and, will be able to be included with applications you develop using Visual Basic and other full-fledged development languages. It is important to remember that net exploring will be a seamless part of the operating system.

Internet Information Server (IIS)


The IIS will also be used by more providers. It's likely that this will initially manifest itself in a groundswell of Intranet installations, since the server version of Windows NT will come with a free copy of IIS, and, new installations don't have to cope with inertia issues (existing Internet providers may for a while be loath to change from their existing web servers, until sufficient user and market demand forces them to upgrade). Fortunately, even though VBScript and IIS dovetail nicely, IIS is not necessary for VBScript page use. Any web server can dish up working VBS-enabled web pages, so long as you avoid any IISspecific functionality.

SQL Server 6.5


SQL Server 6.5 provides Internet-specific hooks, and is designed to work with IIS, as is dbWeb. These tools allow you to easily publish databases on the Internet (or, Intranets). Applications like online order-entry, data reference, and other data-centric systems can become truly practical over the web for the first time.

FrontPage
FrontPage, and other page development systems provide a means to develop and publish web content without having to immerse oneself in the arcana of HTML programming.

VRML

VRML will allow real-time 3-D graphic applications to be run over the web. Uses for this run the gamut from games to medical diagnosis.

ActiveX SDK
ActiveX development is a very broad areaso extensive, that the initial beta version of the SDK was made available as a twelve megabytecompressedfile, and the shipping version commanded a CD of its own. The part we'll be paying particular attention to here is ActiveX controls (formerly called "OCX controls"). These custom controls provide a capability to embed virtually anything on a web page, and VBScript is the language that manages them. The ICP is a set of very useful ActiveX controls that can be used to add anything from email to web browsing to any application written in any language that can use ActiveX controls. By merely setting some properties, and writing a few lines of code, you can add email (sending and receiving), news reading, FTP, HTTP, or nearly any Winsock function required to your applications. Other facets of Microsoft's Internet strategy provide compliance with Java and JavaScript, secure information transfer, merchant services, multimedia broadcast, and so much more as to beg comprehension, let alone description in one book. The list is expected to grow significantly, too!

The Applications
It's often said in this industry that you can always tell who the real pioneers arethey're the ones with the arrows in their backs. Starting out now, you'll be working in largely uncharted territory, with early-generation tools, and most every step you take will take you somewhere you've never been before. In a way, it's no exaggeration to assert that this is the birth of the Internet; yes, it's been around a while, but until now, its growth was largely horizontal. It got bigger and bigger, but it really didn't change all that much, and what change occurred was slow. Now, it's poised to take off, and you're in the pilot's seat. So, where do you take it? Remember, the most important thing is focus. It's easy to succumb to the kid-in-a-candy-store syndrome. All roads lead everywhere, and you're in the middle. The first thing you'll need to bring into focus is the main fork in the road. This is the intersection that leads in one direction to Internet applications, and to Intranet applications in the other. Having found this, you are immediately placed at the head of the pack, since you can safely rely on most of your competitors to frantically dither from one "wow" topic to another.

Cabbages and Kings

Internet and intranet apps are developed using the same tools, and the same skills as each other. But, the targeted users are completely different, and the types of applications are consequently different, too. Intranets will be used by organizations of every stripe. The most immediately visible type will be the corporate organization. But don't forget to consider the wide scope of groups that will be setting up Intranetseducational organizations (universities, public schools, private schools, charter schools, "distance learning" schools, school districts), unions, churches, units of local, state, and federal government (including branches of the above), libraries, insurance companies, law firms, medical groups, and fraternal organizations are just a few of the types of outfits that will be able to make real use of a private, Internet-style network. Internet applications, on the other hand, are for the most part "open to the public." While intranet applications are by nature restricted to those who have physical access to the specific intranet in question, Internet apps that need restricted access (due to content, security, or other considerations) will have to take extra precautions to make sure that only members of the intended audience can gain entry. Security issues are discussed in Chapter 8, "Security."

We can examine some typical examples of VBScript applications (in fact, we'll be doing that in the chapters that follow) but trying to list all possible (or even all likely) uses for VBScript-enabled active content web pages would be an exercise in sheer folly, as well as a serious disservice to you. We can no more reasonably ask "What applications are suited to VBS?" than we could inquire as to which types of programs can be developed in any programming language. While it's true that each language, and each platform, has its own set of features and shortcomings, the fact remains that the scope of possibilities is endless. Just as early predictions of a total worldwide demand of only five or six computers are now seen as absurd, anyone thinking they have a handle on just what types of apps can and cannot be developed with a particular set of tools is going to be astonished at the fruits of the labors of those who refuse to wear a similar set of blinders. With this in mind, let's look at a few representative uses for this technology. Again, it cannot be sufficiently emphasized that this list is non-inclusive. Some typical Internet uses include:
q q q q

Online Catalogs Order Entry Subscription Information Services Pay-Per-Access Information Services

q q q

"Smart" Content Retrieval and Collating "Virtual Community" Creation Games

Naturally, some of these things are already being done now, using earlier technology (server-side CGI scripts, for example). However, their implementations are by nature typically crude, cumbersome, and non-intuitive. By using current (such as VBS) tools to re-implement (as opposed to duplicating) these applications, you'll be able to offer your clients (or employer, as the case may be) a powerful competitive advantage. The real power of active content web programming, however, will be evidenced in new applications applications that are simply too complex and powerful to even consider attempting in "pure" HTML with its, bandwidth-bound, limited intrinsic controls, and complete lack of client-side logic. Although Internet applications will frequently differ in type from Intranet applications, the same abstract reasoning skills are required for development. We'll discuss these considerations after we look at a few typical applications for Intranet installations:
q q q q q q q q q

Data Entry/Maintenance/Reporting Confidential Information Publishing "Virtual Community" Creation Organizational News Reporting On-site and Remote Education Testing and Automated Scoring Online Classes Group Scheduling "Smart" Content Retrieval and Collating

As you can see, there is some overlap, even in the few examples we've provided. Some applications, such as content retrieval, are near-universal in scope, even though actual implementations will vary widely, based on content and context requirements. Both the Internet, and Intranet lists above represent only a smattering of potential applications. You'll easily be able to come up with several others after a few minutes of brainstorming, and even more after discussing possibilities with others.

Implementation
It's a simple word; most of us in this business probably use it at least once or twice a day. This might be a good time to review it, since we're about to experience a tsunami-like event that will affect us all. Whether we accept it with open arms, or are dragged into it kicking and screaming, we will be confronted with, and have to deal with, Internet/Intranet programming issues. Events of these proportions do not happen that frequently. Probably the last time our industry faced similar changes was when Windows 3.0 was released. The last time prior to that was when DOS

killed the future of CP/M. In each of these past events, there were two groups of people: those who said "It'll never fly" (the buggy-whip manufacturers), and, those who realized that they'd better get with the program regardless of their own feelings on the matter. It's no different now. And, while no change is entirely pleasant, we have certain benefits that were unavailable to earlier "pioneers." For one thing, we've seen this happen before. They didn'tat least not to the extent that we have. If we choose to play the "it can't happen here" game, we've only ourselves to blame when we find ourselves out in the cold in the not-too-distant future. Another factor giving us an advantage over our predecessors is the fact that the industry as a whole has matured, platforms and standards are well-established, and fantastic tools are available to implement new solutions. With all this in mind, let's take a brief look at just what makes implementation such an important concept. At one time or another, you've probably found yourself in a situation in which you were being asked to take an existing system, (either paper-based, or running on an earlier non-Windows operating system) and "make a Windows version of it." It's not only large bureaucracies that are subject to inertia. Everyone is resistant to change to one degree or another. This isn't always bad, and is frequently good. However, when it manifests itself in the desire to duplicate an existing system, rather than implementing it in the new environment, there's really nothing at all to be said in its defense. An existing system reflects the limitations of the context for which it was initially developed. It also reflects the constraints imposed by whatever development tools were available when it was created. Attempting to create a "straight port" of the system may indeed be possible, but if you do so, you are doing your client no favor, even if he claims it works and is what he wants. It's not just a matter of cosmetics. Consider the earlier transition from character-based DOS programs to GUI-based Windows applications. There were plenty of straight ports. One language vendor (not, by the way, Microsoft) even developed a library that made it easyit emulated the character-based DOS "interactive" (as opposed to event-driven) interface in a window! When you implement a solution, you have to focus, think, and learn. The goal of this is to be able to intelligently and accurately determine the characteristics of the task to be implemented, and devise a solution offering the most effective combination of ease of use, power, and utilization of the feature set provided by the environment in which you're working. For example, having four hundred small "fill-in-the-blank" fields may be ok on a form printed on a sheet of legal-size paper. Trying to duplicate that monster in a window, however, is nothing short of an exercise in futility.

If you can understand that explaining to the client that there is a better way is not "an excuse" for your inability to create a workable (and identical) duplicate of the existing system, you grasp the principle involved. If, on the other hand, when presented with a situation of this type, your practice is to first try to create an exact duplicate of the existing system, and then try to make excuses for the inevitable problems that ensue, you need to seriously examine the principles we've explored in this chapter. Why is this so important now? The Internet, and the WWW in particular, have overnight become household terms. People who never used a computer before are now running heavy-duty iron, and the only program many of them ever use is their web browser. The user base is therethe demand is thereand the existing systems, ready for implementationare there. There is no way to accurately predict the ground-swell of demand for "computerization." The only thing we can be sure of is that it will be immense. If this next generation of applications is tackled intelligently, thoughtfully, and carefully, we will all benefit greatly. If we jump in and flail away at anything that moves, we'll end up shooting ourselves in the feet. For the first time, we are going to be dealing with mass quantities of people who have existing systems that they will want ported to the net. The keys to bringing about one successful port after another are understanding of the properties of the "new" Internet, and succinctly communicating this to the client. Master what we've covered in this chapter, learn the mechanics of VBScript as presented in this book, and with the right attitude, you'll be one of those who are able to write their own ticket.

Extending HTML
After spending the better part of this chapter with our heads in the virtual-clouds, this topic may seem an odd way to wrap up. But, for better or worse, HTML is currently the Lingua Franca of the Internet, and until the WWW is replaced with something completely different, nearly everything we've discussed in this chapter will have its realization expressed in the form of HTML statements, and scripts contained within HTML blocks. So, let's take a minute or two to get our feet back on the ground, and prepare to segue into the nittygritty of VBScript development. HTML extensions come in two main forms: those that affect appearance, and those that affect behavior. Cosmetic changes are the most visible, but active content is where it's at, and that's where the focus of this book will take you. As you read on, you'll learn how to use VBScript to manage active content, and "glue" together the elements required to move the net beyond "virtual-TV." So go brew a bucket of coffee, get a big box (and clear off the top of your desk into it), fire up

Notepad and Internet Explorer, and dig in!

From Here...
q

q q q q q

See Chapter 2, "Internet Explorer," for a discussion of issues surrounding web browser selection. See Chapters 3-5 for coverage of the ActiveX Control Pad. See Chapter 6, "Review of HTML," for information on HTML language issues. See Chapter 7, "ActiveX Objects," for information on using ActiveX objects. See Chapters 11-14 for coverage of VBScript programming issues. See Chapters 15-20 for intensive VBScript language coverage.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 2 - A Review of HTML


by Yusuf Malluf

q q

q q

q q

q q

The basics of HTML General HTML terminology, elements of HTML such as hyper-linking, multimedia and forms, and the logic of HTML. The extensions made to HTML This includes frames, tables, objects, , and other proposals to the Hypertext Markup Language that have been implemented but not standardized. The future standards of HTML This includes a discussion of proposals to HTML that are still being drafted, such the HTML 3.0 DTD and style sheets. A brief overview of Internet servers and Web browsers Look here for an explanation of the relationship between servers and browsers, and a brief comparison between the leading MS Windows browsers and servers available.

When using Visual Basic Script as one of your Internet authoring tools on the Web, it is necessary to know the medium upon which VBScript rests: Hypertext Markup Language, or HTML. HTML is the standard by which World Wide Web documents are served. VBScript and the ActiveX controls provide a greater degree of interaction inside HTML documents. To become more proficient with Visual Basic Script, it is necessary to understand some key components of HTML and how it works, conceptually. There are two components to creating a hypertext document. The layout or design of the page and the general syntax of Hypertext Markup Language. This chapter primarily deals with the syntax of HTML and the elements that are useful to Visual Basic Script. All of the examples presented in this chapter are created with the use of Microsoft Internet Explorer 3.0 in mind. Many of the HTML elements presented, like style sheets and marquees, are currently supported by Internet Explorer only.

Understanding Core HTML Components


The Hypertext Markup Language is a simple language that was designated as the language for

hypertext communication across the Internet. Its initial advantages were its simplicity and its multiplatform flexibility. Today this phenomena is more than just simple text and graphics rendering, it has become the reality of Cyberspace. There is a standards committee, the World Wide Web Consortium (W3C) which is responsible for establishing standards for HTML and general standards for Internet communication. The W3C is currently.

HTML Terminology and the Logic of HTML

If you have ever seen HTML or have ever heard it mentioned before, some of the terms that may come to mind are elements, attributes, tags, and values. These are all, indeed, simple to understand; but to gain a better understanding of them you must understand the structure of an HTML document. An HTML document consists of two parts: a header and a body. A header is used in specifying the title of the document, the document's owner, and other miscellaneous information dealing with the document. The body portion of the document is where all the displayable content goes. In an HTML document, the header and the body are specified similarly to what is shown in Listing 2.1. You can also get this listing off the CD-ROM in the file FIRSTHTML.HTM.

Listing 2.1 FIRSTHTML.HTMA Simple HTML Document Demonstrating Basic Usage <HTML> <HEAD> <TITLE>The title goes here</TITLE> </HEAD> <BODY BGCOLOR="#FFFFFF"> <P>Just a test - where the body goes</P> </BODY> </HTML> The words surrounded by the < and > brackets are called elements or keywords, whereas the entire keyword including the brackets is called a tag. These tags usually come in pairs, encapsulate a portion of the document, and define what is to happen inside that portion. The <HEAD> and </ HEAD> tags naturally specify the header of the document, and the <BODY> and </BODY> pair specifies the body of the document. The tag examples you see in Listing 2.1 consist of a <Name_of_Tag>, which begins the tag, and </Name_of_Tag>, which ends the tag. Everything encapsulated by these tags is affected by it. Tags can be nested, which means certain tags can be within other tags. The <P> and </P> tags which are used to specify a new paragraph block are nested

between the <BODY> tags. The <HEAD> and <BODY> tags are both nested in the <HTML> and </ HTML> tags (which specify that this is an HTML document).

Remember! You can nest or encapsulate tags in other tags but you can not overlap tags. For instance, the following is not acceptable and is considered bad form: <I><B>This is just a test</I></B> The first tag pair, <I> which indicates that the text is placed in italics and the second pair, <B> which renders text as bold are overlapping. In general, tags overlap when a nested tag is closed outside of the tag pair it is nested in.

Many tags cannot be nested. Tags that are permitted in the header section are usually not permitted in the body, and vice versa. Check Appendix B, "HTML Reference," to see which tags are allowed in the header and body of an HTML document.

Let's examine Listing 2.1 a little closer. The tag that begins the body of the document, the <BODY> tag, has this within the brackets: BGCOLOR="#FFFFFF". The BGCOLOR part of the <BODY> tag is called an attribute. The information to the right of the equal sign is called a value. In this case, the attribute, BGCOLOR, is used to specify the background color of the document. Its value, "#FFFFFF" is the hexadecimal value for the color white. An attribute is an additional keyword to an HTML tag which modifies the tag in some manner. In this case, the BGCOLOR attribute specifies what the background color should be. All attributes for a particular tag are specified when the beginning tag is used (notice there are no attributes for the </BODY> tag in Listing 2.1).

It is always a good idea to surround your values with double quotation marks (""), so the browser recognizes all the information passed as a value as one block.

Microsoft Internet Explorer also uses names for major colors, so you can use the value of "white" for the BGCOLOR attribute instead of "#FFFFFF", which is the hexadecimal value for the color white. Over 100 color names are supported in Internet Explorer 3.0 and these can be found in Appendix B. Additionally, you can specify collapsed hexadecimal color values as well (for example: the value "#F0C" is really "#FF00CC") The singular value specified for the red blue or green section (in the form of #RRBBGG) is duplicated into the other R, B or G slot (for example, the "F" value in "#F0C" is expanded to "FF", and so forth, so the entire value to look like: "#FF00CC").

You know have a foundation for an understanding of how HTML works. Many tags follow the "encapsulation" rule where an opening tag and a closing tag encapsulate some text or other tags. However, there are several tags in HTML which have their exceptions and they will be dealt with in their respective sections.

Linking
Linking is the process of connecting different hypertext documents and other resources on the Internet (or lately, intranets as well). This is easily done with HTML, but, again, some basic terminology must be understood first. The following list acquaints you with some of these terms.
q q

Anchor: Used to indicate a place that references or is referenced by other resources or URLs URL: A Uniform Resource Locater is the standard method of accessing resources by an Anchor Hyperlink: Refers to any clickable object in an HTML page which requests another URL.

The tag which is used for anchoring the is the <A> tag, but it has some required attributes. These required attributes are listed in Table 2.1. Table 2.1 Required Attributes for the <A> Tag Attribute Purpose HREF Used to reference another URL when the text, pictures or other objects encapsulated in the <A>...</A> tags is clicked.

NAME

Used to identify an anchor. This name can be called by other URLS tags with a # appended to the name (for instance, if an <A> tag has NAME="test", then another <A> tag in the document can reference that anchor by <A HREF="#test">...</A> (reference meaning you will go to the place where the named anchor is in the document when clicked.) If the anchor is in another document, then it can be referenced by appending the name, with the preceding number sign to the URL: HREF="http://www.test.com/ test1.html#test" would go an anchor with the name "test" in the file test1.htm at the location of www.test.com.

There are also more attributes that are used with anchor tags, but they are specific to elements like frame sets. The HREF attribute points to some URL, another anchor in the local file or another anchor in a different URL. The NAME attribute can specify a unique identity for each tag in the current or on other HTML documents. Listing 2.2 illustrates how this is done. This listing can also be accessed on the accompanying CD.

The NAME attribute and its new replacement, the ID attribute, have the same function. However, certain tags can not work with the ID attribute (like frames) and some tags will not work with the NAME attribute (like objects).

Listing 2.2 SCNDHTML.HTMA Simple HTML Document That Shows How Linking Works <HTML> <HEAD> <TITLE>A Test demonstrating the anchor tag</TITLE> </HEAD> <BODY> <A HREF="http://www.nm.org"> This Anchor goes to the url http://www.nm.org</A> <A HREF="#bottom" NAME="top"> This tag is called top and references bottom</A> ... <A HREF="#top" NAME="bottom"> This tag is called bottom and is referenced by top</A> </BODY></HTML> This is all there is to hyperlinking, but also keep in mind that you can put many things in an anchor,

including pictures, which become clickable images. Other HTML tags that rely on (or are indirectly used by) anchors are image maps, frames, and forms. In Visual Basic Script, the NAME attribute is used extensively throughout documents that contain those scripts because Visual Basic Script has the capability to use those names to make HTML more interactive. You may find, though, that Visual Basic Script is used extensively with forms and input boxes, which are discussed later in this chapter.

Images and Multimedia


Images and multimedia also help to make hypertext documents more interesting. When dealing with graphics, the major HTML tag associated with multimedia is the <IMG> tag. With the <IMG> tag, you can specify what picture to display, and the dimensions of the picture. Also, with an <IMG> tag you can display different animation clips to play. The Microsoft Internet Explorer supports inline AVI animation clips. Listing 2.3 is an example that stresses the major features of the image tag. This example is illustrated in Figure 2.1. Listing 2.3 may also be found on the CD that accompanies the book. Notice that the clickable image has a border around it. Images that are clickable usually are surrounded by a border indicating that it is a link. The attributes for controlling borders and clickable images are covered fully in Appendix B.

Listing 2.3 PICSDEMO.HTM The Different Ways to Use the <IMG> Tag <HTML> <HEAD> <TITLE>This page stresses the major features of the IMG tag.</ TITLE> </HEAD> <BODY> <IMG SRC="test.gif" HEIGHT="100" WIDTH="100" ALIGN="left"> This is an image that will be rendered 100x100 pixels <BR CLEAR="left"> <A HREF="test.html"><IMG SRC="test.gif" WIDTH="100" HEIGHT="100"> </A>This image is clickable

<BR CLEAR="left"> <IMG DYNSRC="test,avi" LOOP="infinite" START="mouseover" WIDTH="100" HEIGHT="100" ALIGN="CENTER"> This a centered picture of an AVI file. Move the mouse over it. </BODY></HTML> FIG. 2.1 This figure demonstrates the different uses of the <IMG> tag. This example displays three different ways to use the IMG tag. The first example displays a normal image that is left aligned, 100 pixels long, and 100 pixels wide. The next is a clickable image, which you can tell because it is encapsulated by the <A></A> tags. The final example shows how to display an AVI animation which plays infinitely (specified by the LOOP attribute) and only plays when the mouse is moved over the animation (specified by the START attribute). One other interesting HTML addition is the MARQUEE tag. With this tag, you can make text and other objects encapsulated in the marquee scroll across the screen. Graphics and multimedia are very useful for Visual Basic Script and the ActiveX environment, because it obviously enhances the interaction capability of the page by providing interactive animations and even games. More information on both these tags can be found in Appendix B at the end of the book.

Forms and Their Interaction with Visual Basic Script


HTML forms are where Visual Basic Scripts can be very handy and helpful to use. Originally, forms were usually processed and validated the Common Gateway Interface (CGI). With the CGI method, a third source was involved in processing and validating all the information provided by forms and other interactive programs. This was usually implemented by the Web server that hosted these pages. With the introduction of scripting languages, such as Microsoft's Visual Basic Script and Sun's Java, everything has changed. With the inline scripting capabilities provided by these script languages, most of the processing is done at the client's side, or on your computer. As a matter of fact, many tasks involving scripting can be done on the client's side. In this section, forms are covered in depth, since they are one of the major applications of Visual Basic Script. Forms are fairly simple, but there are several more HTML elements that make forms what they are. A pair of <FORM> tags encapsulate everything that is related to the form, and everything that is submitted in that form. The form's controls can include input boxes for entering text, radio buttons for specifying one choice out of several, select boxes, which are drop-down menus of different selections, and buttons, which can reset, submit, or perform other tasks with the form. According to the HTML specification, the general syntax for specifying a form is:

<FORM ACTION="POST/GET" METHOD="URL"> ... </FORM>

The ACTION attribute specifies what URL to go to for processing data. The METHOD attribute specifies what method the data should be given for processing by the URL specified by ACTION. However, the ACTION and the METHOD attributes are not necessarily needed for use in Visual Basic Script. Since the script is being used internally, it is redundant to specify what URL is needed to process the form. The following example shows how Visual Basic Script uses a form. You don't need to understand all the specifics of the form now, because they are fully covered later in this chapter or in subsequent ones. Listing 2.4, FORMDEMO.HTM is a simple form. This listing is illustrated in Figure 2.2 and can be found on the CD under the file name FORMDEMO.HTM.

Listing 2.4 FORMDEMO.HTMA Simple HTML Document That Demonstrates How a Form Works with VBScript <HTML> <HEAD> <TITLE>This is a page which demonstrates how vbscript functions with forms</TITLE> </HEAD> <BODY BGCOLOR="#DDFFFF"> <CENTER><FONT FACE="Arial" SIZE="4" COLOR="blue"> How to use forms with VB Script</FONT></CENTER> <HR> <PRE><FORM NAME="me"> The text typed here : <INPUT TYPE="text" VALUE="Default" NAME="test1" SIZE="50"> Will go here when the button is pressed: <INPUT TYPE="text" VALUE="Hello" NAME="test2" SIZE="50"> <CENTER><INPUT TYPE="BUTTON" NAME="but1" VALUE="Push Me"></ CENTER> </PRE> </FORM> <SCRIPT LANGUAGE="VBS"> Sub but1_OnClick Set Form=document.me Form.test2.Value = Form.test1.Value End Sub

</SCRIPT> When viewed with Internet Explorer 3.0, the first text box has the text "Default" and the second text box has the text "Hello." When you click the button, the text in the first box replaces that in the second, producing "Default" in both boxes. This example is shown in Figure 2.2. FIG. 2.2 An example of a form created with VBScript. This is a pretty simple form with some Visual Basic Script capabilities. There are a few new tags to consider in this document. The tags such as <FONT> and <PRE> are for cosmetic purposes only. The substance of this document lies in the <FORM> and <SCRIPT> tags. The form and its controls (for example, input boxes, radio buttons, and so on) are just HTML tags, and everything inside the <SCRIPT> tags is Visual Basic Script used for manipulating those tags. Let's consider a few things inside the form. First, we assign the form a name, "me", and this is the name used by the script. Next, we have a few <INPUT> tags with no </INPUT> because they do not encapsulate any text, but define a control to use, the control's name, and any values associated with it. Finally, we have a button control, and that is the end of the form. The <INPUT> tags both have a NAME, TYPE, and VALUE attribute. The TYPE attribute in each tag is set to "text," which is a text input box with a size of 50 characters. The NAME is the input box's unique identifier and the VALUE is the default value that is first seen in the box when the page is viewed. Table 2.2 shows the different form controls, specified by the TYPE attribute and used in the <INPUT> tag. Table 2.2 Values of Form Controls Used by the TYPE Attribute of the <INPUT> Tag TYPE Value Function "text" "password" "radio" Specifies a one-line text box. Similar to the "text" value, except the characters are not seen and are usually replaced by one similar character. Can specify a series of buttons with the same value for the NAME attribute, but only one of the buttons can be chosen. Specifies individual text boxes with different values for NAME; additionally, the VALUE attribute must have a value of TRUE or FALSE (TRUE means it is initially checked and FALSE means it is not initially checked. Specifies a hidden field, which should contain a VALUE attribute. This control is not seen by the user. Creates a button that submits the form to the URL specified by the ACTION attribute of the FORM tag. Creates a button that clears all the entries on the form.

"checkbox"

"hidden" "submit" "reset"

"button"

Creates a button that can be referenced by Visual Basic Script; a name can be given to the button (and all buttons) by giving a value to the NAME attribute. A name that is displayed on the button can be given by assigning a value to the VALUE attribute of the button. Instantly submits the form when clicked, with the coordinates of the position of the mouse-click on that image. Specifies several lines of input text similar to the one-line text box control.

"image" "textarea"

The image control requires the additional attribute, SRC to specify a graphic to use. All input types should have a NAME or ID tag to be manipulated by Visual Basic Script. The size allotted to the text control is lengthwisefor example, <INPUT...SIZE="50">whereas the textarea control's size is given by length and height, respectivelyfor example, <INPUT... SIZE="50,50">.

In addition to the input tag, there are also a few other controls, such as combo boxes and drop-down lists, that can be used in forms and manipulated by Visual Basic Script. These additional tags are shown in Table 2.3. Table 2.3 Additional Form Tags Control Tag Function Can specify a drop-down list or a list box depending on whether the attribute <SELECT> MULTIPLE (has no value) is present. If MULTIPLE is present, then it is a scrollable list box, which allows the user to select more than one option from the list. Is encapsulated inside the <SELECT> tags and specifies the name and values for the <OPTION> various list options of that combo box or drop-down box with the NAME and VALUE attributes.

The SELECT tag, unlike the INPUT tag, has a closing tag (for example, <SELECT>...</ SELECT>). The NAME and VALUE attributes associated with the OPTION tag deal with the data that is submitted when that option is selected, and not with the text that is displayed when the form is viewed. The text which describes the option on the screen immediately follows the <OPTION> tag (for example, <OPTION >Displayed text here). The <OPTION> tag does not have a closing tag.

This wraps up forms and their usage. For a more elaborate example that uses all the FORM controls, refer to FORMCOMP.HTM (on the CD), which has output as shown in Figure 2.3. The other major tag mentioned, the SCRIPT tag, is used to specify a scripting language to use. In this book, the script language is exclusively Visual Basic Script. The LANGUAGE attribute of the SCRIPT tag defines what language the script is interpreted in. The value for this language, "VBScript", specifies Visual Basic Script. The SCRIPT tag also has a closing tag. FIG. 2.3 A more complete demonstration of forms.

Make sure you include the closing tag, </SCRIPT>, at the end of your Visual Basic Script; otherwise it does not execute.

It may be helpful to surround your entire Visual Basic Script with a comment so the script is not displayed on browsers that do not support it.

Using Extensions
To this point we have discussed HTML entities that will more or less remain the same with minor additions now and then. In this section, many of the important extensions made to HTML are covered. It is fair to say that Netscape Communications, Inc. was the first company to implement several extensions to the HTML language, including background colors, the ability to center text, frames, and so on. Microsoft and its product, the Internet Explorer, has also made many contributions to HTML including client-side image maps, marquees, smoother support for tables and frames, objects, and, of course, the ActiveX controls. Many of these entities such as objects and the ActiveX controls are very useful to Visual Basic Scriptsome of which were demonstrated in Figure 2.3. As previously stated, the tags and entities dealt with in this section have great potential for change, as the standards have not yet been decided on by the HTML standards committee at the World Wide Web Consortium (W3C).

Base Attributes
A system of base attributes, which are intrinsic to every tag, has been proposed and is largely implemented in Internet Explorer's implementation of HTML. Table 2.4 lists some of the base attributes which have been already implemented and a brief explanation. Also remember that these tags primarily effect tags that are used to render text. Table 2.4 Supported Base Attributes Attribute name Purpose CLASS Used to commonly group a tag or set of tags. This base attribute is used mostly with Style Sheets to specify rendering properties for different classes (groups) of tags. Used to identify other tags besides the anchor tag. These tags are also used with style sheets to set certain styles to tags which have styles for the name they use in the style section of a document (see the style section). In future versions of Internet Explorer 3.0 however, there might be support for the <A> to access other tags with NAME and ID attributes in the same manner as it would access other <A> tags with the NAME/ID attribute.

ID and NAME

Extensions of HTML
In addition to entire tags extending the HTML language, there have been several minor extensions to existing tags, some of which were demonstrated in prior sections. These are covered here, briefly. To begin with, the IMG tag has the attribute extension, DYNSRC, which allows the author to embed inline AVI animations. The DYNSRC attribute specifies which animation to play that has several additional attributes that enable you to customize the way the AVI animation looks and plays. When you encapsulate an image tag with an anchor, you can allow a Visual Basic Script to utilize this image from within the script(demonstrated in Figure 2.3). The input tag that is used inside the form to specify form controls also has the new button control, which allows you to specify other buttons on the form instead of your every day submit and reset buttons. The ALIGN attribute works with most of the HTML tags which affect text in some manner. The ALIGN attribute is used to specify where the text or other object should be displayedusually with the values "left" and "right", although "center" is used, it has not been implemented on all tags.

HTML Tables
The introduction of tables into the HTML language has vastly improved the way data is handled and content is served. Tables provide an efficient way to handle and organize data and Web pages, which formerly would have been accomplished by images and pre-formatted text tags! This section discusses the table's basic usage, the various types of tables supported, and a couple of methods for

implementing different tables. Figure 2.4 is an example of a basic HTML table, which has several rows and columns and a caption. FIG. 2.4 A sample HTML table. This table demonstrates several of the basic tags used in tables. The code for this table is in Listing 2.5, which can be found on the CD in the file TABLE1.HTM.

Listing 2.5 TABLE1.HTMA Brief Example of Tables in HTML <HTML><HEAD> <TITLE>This is a simple Table</TITLE> </HEAD> <BODY BGCOLOR="ALICEBLUE"> <H1 ALIGN="CENTER">A Simple Table Example!</H1> <CENTER> <TABLE CELLPADDING="5" CELLSPACING="2" BORDER="2" BGCOLOR="#CDCDCD"> <CAPTION ALIGN="BOTTOM"> <B><I>Some Species from the Suborder Microchiroptera</I></B></ CAPTION> <TR> <TH ROWSPAN="7" BGCOLOR="LIME">Family<BR>Molossidae</TH> <TH><FONT SIZE="4" FACE="ARIAL" COLOR="RED">Species</FONT></TH> <TH><FONT SIZE="4" FACE="ARIAL" COLOR="BLUE">Common Name</ FONT></TH> </TR> <TR><TD><I>Tadarida aegyptiaca</I></TD> <TD><B>Egyptian free-tailed bat</B></TD></TR> <TR><TD><I>Tadarida africana</I></TD> <TD><B>African giant free tailed bat</B></TD></TR> <TR><TD><I>Tadarida australis</I></TD> <TD><B>Southern mastiff-bat</B></TD></TR> <TR><TD><I>Tadarida brasiliensis</I></TD> <TD><B>Brazilian fre-tailed bat</B></TD></TR> <TR><TD><I>Tadarida lobata</I></TD> <TD><B>Kenya big-eared bat</B></TD></TR> <TR><TD><I>Tadarida macrotis</I></TD> <TD><B>Big free-tailed bat</B></TD></TR>

</TABLE></CENTER></BODY></HTML> A table in HTML, which is similar to the form, uses the <TABLE> and </TABLE> tags, which initiate the table and specify the table boundaries (everything inside the <TABLE> tags is affected by the table). Table 2.5 lists the four major tags used inside a table. Table 2.5 The Four Main Tags for a Table Table Tag Purpose Specifies a row to be used in the table. This should be the first tag used when actually constructing a table. Any test or HTML that is inside the <TH> tags is considered the heading of the table. Each instance of the <TH> tag denotes a cell in the table which must be encapsulated in the <TR> tag. All cells that are in a <TR> tag are arranged horizontallyfor example: <TR><TH>Header 1</TH><TH>Header 2</TH></TR> would be a row with two columns; the first column has "Header 1" as its text and the second "Header 2" as its text. By default, all text encapsulated in the <TH> tags is centered and rendered in bold. Specifies table data in the form of cells which functions the same as a <TH> tag does. All instanced of <TD> nested in a <TR> tag are placed horizontally in columns.

<CAPTION> Specifies a caption for the table. <TR>

<TH>

<TD>

The four major tags listed in Table 2.5 were used in Listing 2.5. There are also attributes to each of these tags. The attributes listed in Table 2.6 will work with the <TR>, <TH>, <TD>, and <TABLE> tags. The <TR>, <TH>, <TD>, and <TABLE> tags work by inheritance. Inheritance, in terms of HTML, means that whatever attributes are specified by a tag are used by tags which are encapsulated by it. However, if these child tags (tags that are encapsulated by the parent tag) have their own attributes defined, then these are used instead for tables. Table 2.6 Attributes for <TABLE> Tags Attribute ALIGN BGCOLOR Function Specifies the alignment of the table or text in the table. Values of "left" and "right" are supported. Specifies the background color of the table, which uses either Internet Explorer colors or colors given by hexadecimal RBG.

BACKGROUND Specifies an image to use as a background of table cells. The image is tiled. BORDERCOLOR Specifies the color of the border of the table. Works similarly to BGCOLOR. VALIGN Specifies where the text is to be vertically aligned in each cell. Values for this attribute are "top", "bottom", "middle" and "baseline".

COLSPAN ROWSPAN WIDTH HEIGHT

Specifies how many columns a particular cell should span across (used with <TD> and <TH> only). Specifies how many rows a particular cell should span across (used with <TD> and <TH> only). Similar to COLSPAN, except that pixels or a percentage of the screen are used for the span value. Similar to ROWSPAN, except that pixels or a percentage of the screen are used for the span value.

Additionally, there are other, minor attributes dealing with detail in border color and spacing that are not covered here. A full review of table styles can be found in Appendix B, "HTML Reference," of this book. For extensive coverage on the HTML language, check out Que's Special Edition Using HTML. There are also different styles for tables. Some tables can be defined in terms of header, body, and footer, and some can be defined in terms of columns instead of rows, according to the HTML 3.0 Standard. Borderless tables can be used to make a page look very stylish by using them to set different areas of the page with different background colors or images in the table's cells. Listing 2.6 shows how to use borderless tables with different background colors and images to make a page look interesting. Figure 2.5 illustrates Listing 2.6. You can find the listing on the CD-ROM in the file TABLE2.HTM.

Listing 2.6 TABLE2.HTMSome Techniques for Creating an Interesting Page with Tables <HTML><HEAD> <TITLE>This is table demo 2 - how to use tables for page layout... </TITLE></HEAD> <BODY BGCOLOR="BLACK" TEXT="#FFFFFF"> <TABLE> <TR><TD BGCOLOR="BLACK" WIDTH="150" HEIGHT="50"> <FONT FACE="MS Sans Serif" SIZE="3" COLOR="RED"> <CENTER>MALLUF Travel Agency</CENTER></FONT> </TD> <TD WIDTH=500" ><FONT FACE="WINGDINGS" SIZE="20" COLOR="ORANGE"> <MARQUEE DIRECTION="RIGHT">Q</MARQUEE> </TD> <TD WIDTH="100" HEIGHT="100"> <IMG DYNSRC="TheEarth.avi" HEIGHT="100" WIDTH="100"

LOOP="INFINITE"> </TD></TR></TABLE> <TABLE CELLSPACING="20" CELLPADDING="10"> <TR><TD VALIGN="TOP" WIDTH="600" HEIGHT="350" BGCOLOR="RED"> <H2>Tours to Earth Special</H2> We are offering a 50% discount for a 2 passenger flight to Earth! What a deal! Get away from those orbiting atrocities and have a taste of reality. <HR><H2>Universal Discount</H2> That's right! For the month of April, we are offering universal discounts, for free flights to Mars, Jupiter, Earth and Venus. <HR>A Service of MCS. Your ONLY universal affiliate.</TD> <TD WIDTH="625" VALIGN="TOP" BGCOLOR="BLACK" ALIGN="RIGHT"><CENTER> <IMG SRC="bigm.jpg"></CENTER> </TD></TR></TABLE></BODY></HTML> FIG. 2.5 This is an example table of Listing 2.6. This figure illustrates some of the techniques used for making stylish tables. Consider Listing 2.6; two tables were used in this example. There are several interesting ways tables are used here. First, the lengths and widths of each of the table's cells are not uniformly positioned which causes different areas covered by these widths to contain different colors and styles. Also notice the Marquee that is nested in the <TD> tag with a width of 500 pixels, which spans across the screen to the cell which contains the AVI of the Earth spinning. The airplane shown, and other icons can be displayed in this manner by using the Wingdings or Dingbats fonts (the <FONT> tag should surround the marquee, but not vice versa). The example in Listing 2.6 demonstrates a basic method of page layout. Other alternatives include style sheets (which are covered in this chapter) and ActiveX controls (which are covered in depth in Chapter 11, "Designing VBScript Applications").

HTML Frame Sets


This section discusses one of the more recent extensions to the HTML language, which allows the existence of multiple HTML documents or other resources on one page. Frame sets are an efficient, neat, and effective way to organize and present information in an HTML document. Frame sets are a group of frames in an HTML document each of which display a different resource (an HTML file, for instance). A frame set is relatively simple to understand. Frame sets are used within the <BODY> tag and replace any content which would otherwise exist inside the body of a document. There are two parts to a frame set. The general tag for specifying a frame set and the properties of all frames in the frame

set (this tag is the <FRAMESET> tag) and the tag which is used to indicate the frames (the <FRAME> tag). The general syntax is expressed in the following syntax section. A simple demonstration of a frame set is shown in Figure 2.6. The code to this figure is in Listing 2.7. FIG. 2.6 This figure illustrates some basic uses of frames.

Listing 2.7 MAINFRAME.HTMThe HTML File That Specifies All the Other Frames and Files to Use <HTML><HEAD> <TITLE>This Document Demonstrates Frames</TITLE></HEAD> <FRAMESET COLS="50%,*"> <FRAME SRC="frmfile1.htm" SCROLLING="no" NAME="frame1" FRAMEBORDER="1"> <FRAMESET ROWS="40%,*"> <FRAME SRC="frmfile2.htm" SCROLLING="yes" NAME="frame2" [ccc] FRAMEBORDER="yes"> <FRAME SRC="http://www.rt66.com/iymalluf" SCROLLING="yes" [ccc] NAME="frame3"> FRAMEBORDER="yes"> </FRAMESET> </FRAMESET> Notice that there are a few new tags introduced with frame sets. The first tag, the <FRAMESET> tag is used to define the length of the frames, how many there are and how they are to be rendered. Next, we have the <FRAME> tag which is used for specifying the actual content of the frame which was defined by the <FRAMESET> tag (see Listing 2.8). The SRC attribute of the <FRAME> tag is used to specify the URL of the file it is to display. These files are below.

Listing 2.8 FRMFILE1.HTMFirst File Used with Frames <BODY BGCOLOR="LIME" TEXT="PURPLE"> <CENTER>

<FONT SIZE="5" FACE="Matura MT Script Capitals" COLOR="PURPLE"> My File</FONT></CENTER> <HR> This is the daily chatter column; anything goes here, except you shouldn't be overly rude or excessively fastidious. Here is the first frame, hope you enjoy!! <HR> </BODY> This is the first file used with the first frame defined in the previous code example. The files displayed in frames are nothing but individual HTML documents, so whatever you can do in an HTML document is valid content for a frame. Listing 2.9 illustrated another use of frames.

Listing 2.9 FRMFILE2.HTMSecond File Used with Frames <BODY BGCOLOR="BLUE" TEXT="LIME"> Here are some quick facts about physics: <OL> <LI>It's the study of matter</LI> <LI>It involves the study of Quantum mechanics wave theory</LI> <LI>Facts are subject to change at any time</LI> <LI>Most general equations were derived with ide00al situations in mind</LI> </OL> </BODY> This is the second file which is used with the second frame. It is also another HTML document. Since you can use any HTML document for content for a frame, you can also add background colors or images to the frames. Syntax of Frames and Frame Sets The tag used to specify a frame set is the <FRAMESET> tag and it has a closing tag, </ FRAMESET>. Contrast this to the <FRAME> tag that has just one tag specifying what is to be in a

frame. Some attributes for the <FRAMESET> tag are in Table 2.7 and the general syntax is below: <FRAMESET> <FRAME> ... </FRAMESET> There are also a few required attributes for the <FRAMESET> and the <FRAME> tags and they are listed in Tables 2.7 and 2.8. Figure 2.6 illustrates a simple layout of a frame set. The files MAINFRAME.HTM, FRMFILE1.HTM and FRMFILE2.HTM are used for this example and can also be found on the accompanying CD. Table 2.7 Required Attributes for the <FRAMESET> Tag Attribute Function COLS Used to specify the number of columns in a frame set and their width. The number of columns in a frame set is specified by how many comma separated values exist for this attribute (the values represent the columns width). Used to specify the number of rows and each row's height in a frame set. The number of rows in a frame set is specified by how may comma separated values exist (these values specify the length of each row).

ROWS

In the <FRAMESET> tag, either the ROWS attribute or the COLS attribute can be used, but not both. The ROWS and COLS attributes are used in specifying how many frames are to exist in a frame set, their width or height and how they should be displayed (as rows or columns, based on which attribute is used). The number of frames that are to exist in and their length are both specified at once. The number of frames are specified by how many comma-separated values exist in the ROWS or COLS attributes. These comma separated values specify the length of each frames. So if you have 3 length specified for the ROWS or COLS attributes, then you use three frames, or other nested <FRAMESET> tags. For example, if one wanted a frame set which consist of two columns, one that is 300 pixels and the other which takes up the remainder of the space they would do the following: <FRAMESET COLS="300,*"> <FRAME SRC="somefile.htm"> <FRAME SRC="somefile2.htm"> </FRAMESET>

Note that two <FRAME> tags are used. There are two <FRAME> tags since there are two values specified. The <FRAME> tags correspond to the lengths specified by the <FRAMESET> tag in the same order that they are specified. So the first value of 300 in the COLS attribute is assigned to the first frame specified, and so on. There are three ways to specify a length for the COLS and ROWS attributes. These valid values are in the following list.
q

Pixels: When you wish to use pixels to specify a length, then you use any integer up to the maximum width or height of the browser. For example: COLS="300,200"" specifies two columns in a frame set, the first is 300 pixels wide and the second is 200 pixels wide. Percentage of screen: Lengths are specified as a percentage of the screen. Valid values are a number (up to 100) with a % sign appended to the end representing how much of the available screen space to use. For example, ROWS="10%,90%" would create two rows. The first row uses 10% of the height of the screen and the second uses 90 percent (or the rest) of the screens height. Relative size: Using relative values, you specify how much space to use based on how much the other frames have used. Relative values are specifed by a * or a number with the * appended to represent a relative proportion to other relative values. For example: ROWS="3*, *" would create two rows. The first uses 3 parts (3/4) of the screen and the second uses one part (1/4). These frames are relative to each other so if the size of the browser window changes, their lengths will remain in this proportion. A combination of lengths: You can use one or more of the previously mentioned methods for specifying lengths of frames. For instance: COLS="100,20%,*" would specify three columns. The first column is 100 pixels wide, the second uses 20 percent of the remaining screen and the final column uses the remainder of the screens width.

The attributes for <FRAME> are in Table 2.8. Table 2.8Attributes for the <FRAME> Tag Attribute SRC NAME SCROLLING NORESIZE Function Specifies what URL the frame should point to. Gives an identification to the frame, so other links can manipulate the frame. Specifies if the frame is capable of scrolling (valid values are "Yes" and "No"). Is an attribute with no value. It is inserted into the <FRAME> tag if the person designing the frames does not want the user to resize the frame.

FRAMEBORDER Specifies if the frame has a border (valid values are "Yes" or "No"). FRAMESPACING Makes the spacing between frames larger. Again, note that these are not all the attributes that are available for the <FRAME> tag. There are other attributes, however; they are either for cosmetic purposes. These minor attributes are covered fully in Appendix B, "HTML Reference."

For browsers that do not currently support frames, you can add the tag <NOFRAMES> to the very end of your document and treat the content encapsulated in the <NOFRAME> tags like the content in a normal HTML document, which has <BODY> tags.

Manipulating Frames As previously mentioned, you can manipulate frames in HTML with anchor tags and anything else that can reference another URL. To do this, you must include the TARGET attribute in your anchor tag. Whatever URL the anchor is pointing to is displayed in the frame specified by the TARGET attribute when that anchor is clicked. The TARGET attribute is used to specify the name of the frame to put the resource in. If you have a frame named "test1," to access that frame through a link, you would have to put TARGET="test1" as an attribute in the anchor tag. Refer to Listings 2.102.13 for a full example. This example covers the basic uses of frames that we have already discussed. These listings can also be found on the accompanying CD under their respective file names. Figure 2.7 illustrates this basic example.

Listing 2.10 FRAME2.HTMAn Example of Frames and the TARGET Attribute <HTML> <HEAD><TITLE>This is a frame page demonstrating the TARGET attribute </TITLE></HEAD> <FRAMESET ROWS="25%,*"> <FRAME SRC="links.htm" SCROLL="no" FRAMEBORDER="yes" FRAMESPACING="4"> <FRAME NAME="linktarget" SRC="blank.htm" SCROLL="yes" FRAMEBORDER="yes" [ccc] FRAMESPACING="4"> </FRAMESET> Listing 2.11 LINKS.HTMThis is the First Frame of the Frame Set <BODY BGCOLOR="WHITE"> <CENTER> <FONT FACE="COMIC SANS MS" SIZE="+1" COLOR="BLUE"> Click-a-link!</FONT><BR>

<TABLE CELLSPACING="2"> <TR> <TD> <A TARGET="linktarget" HREF="http://www.nm.org/ ~chfaq">Supercomputer Challenge</A> </TD> <TD><A TARGET="linktarget" HREF="http://tesuque.cs.sandia. gov/"> Adventures in Supercomputing</A></TD> </TR> <TR><TD><A TARGET="linktarget" HREF="http://www.mcp.com/ que">QUE [ccc] Corporation</TD> <TD><A TARGET="linktarget" HREF="http://www.rt66.com/ iymalluf">Malluf [ccc] Consulting Services</A></TD></TR> <TR><TD><A TARGET="linktarget" HREF="http://www.microsoft. com/"> Microsoft Website</A></TD> <TD> <A TARGET="linktarget" HREF="http://www.yahoo.com">YAHOO</A></ TD></TR> </TABLE></CENTER></BODY>

Listing 2.12BLANK.HTM This Is a Blank File Used by the Second Frame <BODY BGCOLOR="#000000"> </BODY> FIG. 2.7 An example of frames and the TARGET attribute. This is a simple frame set demonstration that allows content specified by links in the first frame to be placed in the second frame when clicked. The TARGET attribute also has several special values which are listed under the Frames section of Appendix B. Using Frames with Visual Basic Script When using frame sets and Visual Basic Script together, you are providing a higher level of interactive HTML documents and Web pages. With Visual Basic Script and frame sets, you can make

interactive games, more advanced ordering systems, and electronic catalogs. You can use Visual Basic Script inside each frame and scripts that are used in other frames in the frame set can be accessed using the frames collection of Visual Basic Script (refer to chapter 11 for a description of the frames collection under the Internet Explorer 3.0 Object Model section). This section basically covers frame sets and their usage. Next we'll look at some very recent components of HTML that work very nicely with Visual Basic Script.

Scripts in HTML Documents


Scripts are the whole basis for Visual Basic Script and other inline scripting languages. Scripts are used for a number of things in an HTML page. Some of these tasks have already been mentioned, like a validation tool for forms, games and electronic magazines (E-zines). The <SCRIPT> tag specifies what scripting language to use in the HTML document. There are also several attributes that make the <SCRIPT> tag as advanced or as simple as you want. For most purposes, though, only the LANGUAGE attribute needs to be used. This attribute specifies which language to use. If the language is Visual Basic Script, then you would insert the following in your <SCRIPT> tag: LANGUAGE="VBScript". If the language is Sun's JavaScript, then LANGUAGE="Javascript", and so on. Table 2.9 shows the different attributes used with the <SCRIPT> tag. Table 2.9 Attributes for the <SCRIPT> Tag LANGUAGE Specifies the language the corresponding script uses Specifies what the script should "bind" to, as in a form or some other group of elements that fall under one NAME or ID. For example, if a form was named "form1" and you wanted to access the controls in that form with VBScript, then you would use: in="form1", which specifies that this script is used for the controls in this form.

IN

Style Sheets

If you are not familiar with HTML beyond what you have read in this chapter, it is recommended that you review Appendix B, "HTML Reference," to understand the tags discussed in this section, which not mentioned in this chapter.

Style sheets are the newest introduction to the HTML Language. Style sheets allow a user to have a

collection of HTML documents or an entire Web site use one or several formats of style which was formerly accomplished by the tedious task of inserting many <FONT> tags, graphics and other miscellany into an HTML document. Microsoft Internet Explorer is the first browser to implement style sheets to a useable level. Formerly, the UNIX based browser, Arena had some style sheet support but lakcs in many areas support; Microsoft Internet Explorer hosts several additional features to its style sheet implementation. This section covers the concept of style sheets, how to use style sheets and their integration with HTML. How Style Sheets Work This section describes the concept behind style sheets and how they work. A style sheet does not only apply to the page's style in general, but also to the tags used on that page. For instance if one wanted all <H1> headers in a page to be rendered as a size 14 pt. and the face of the font to be Arial, he or she could used style sheets to change all those headers. If one only wanted specific <H1> headers to be 14 pt. and Arial, and other 16 pt. and Matura, he or she could use the CLASS base attribute to assign certain headers to be of the former style and other headers to be the latter style. How to Use Style Sheets This section covers the syntax of style sheets, how and when to use them. The syntax for style sheets is a little different from the syntax of HTML but it is almost as simple. There are three major ways to use style sheets with an HTML document and they are in the following list.
q

Pre-defined styles in a separate file: You can predefine styles in a file to use on a page. This is most efficient when there are several pages that need to comply to the same style. The syntax will be covered in the syntax section. Inline-defined styles: You can define styles for different tags within the document as well. With the current implementation of Internet Explorer, however, if there is a file-specified style format, it will override any inline styles. This will be changed in a future release. Tag-specified styles: There are a series of HTML tags for style sheets that you can use in the body of your document to change the style of text and other entities. These tags allow you to change the style the same way as inline styles and styles stored in a separate file.

Syntax This section covers the general syntax for defining styles for different elements in HTML. When specifying a series of styles that are located in a file you have to use the <LINK> tag in this format: <LINK REL="STYLE" TYPE="text/css" SRC="URL"> The <LINK> tag is used to specify files that are related to the document with that link tag. The attributes in this link tag are described in Table 2.10. Table 2.10 Attributes of the Link Tags for Style Sheets

Attribute Function REL Specifies a relationship for the <LINK> tag. In this case, the file specified in the <LINK> tag has the relationship "style" which, of course, indicates that the corresponding file is a style sheet. Specifies a MIME type which states that the text in the file specified is a style sheet. The value "text/css" is used to indicate that the file is a style sheet. Specifies the name of the file to use. This can either be the name of the file (I.E. style. css) or the URL to that file (http://www.somewhere.org/styles/style.css).

TYPE SRC

The file method for specifying a style sheet works across a server only, which means that this method will not work on your machine alone. The file must be requested across the server. The server must have the MIME type: text/css for the extension .css for this method to work across a server.

You should always name your files that contain style information with the extension .css, so it is recognizable by the server as a style sheet file.

When you specify inline style information, you have to use the <STYLE> tag, which should be used outside of the body of an HTML document (preferably inside the header of the document). The <STYLE> tag also has a closing tag </STYLE> and all the defined styles are to be encapsulated in the <STYLE> tags. Each defined element can have a series of styles; the syntax is listed below: TAGNAME {style1: value1; style2: value2; ...}

When you use style definitions which are on a separate file, you use the syntax in this section, without the <STYLE> tags. Any number of style definitions can exist in this file.

TAGNAME is a pseudonym for any text rendering HTML element. Following this tag is a pair of curly braces ({ and }) in which are all the style properties for that element's corresponding tag (the element with the "<" and ">" brackets); style1 and stlye2 ... are pseudonyms for the different style properties for that element. Note how this varies from attributes and values in HTML. A property and its value, in style sheet syntax, are separated by a colon instead of the equal sign. For instance: A {text-decoration: none} is used to specify no additives to the <A> (anchor) tag (like underlines and strikethrough). Textdecoration is a property of the A tag which is set to the value none which means no text decoration. All tags share the same set of properties listed in Table 2.11. Table 2.11 Style Properties for Use with Different HTML Elements Property Name Function and Allowed Values Specifies the fonts used with the specified element. Any font name is allowed (as long as the font is on the user's systemsee the appendix under the <FONT> tag for some common fonts. Fonts can be separated by commas to indicated different fonts to use. (for example: ...{font-family: Arial, Times} If the first font in the list is not available, the browser checks to see if the next is available, and so on until it finds a font that is on the user's system, if none of the specified fonts exist, the default font (Times New Roman) is used. Any number of fonts can be specified. Specifies the size of the font using several different measurements, listed in Table 2.12. Valid values for font size's are a number with one of the abbreviations listed in Table 2.12 appended to it. Specifies the weight of the font. Valid values are bold and normal (ie: ...{fontweight: bold; ...} sets the font-weight for the specified element to bold. Sets the style of the font. Only the value of italic is supported currently (for example: ...{font-style:italic;...) would set the style of the corresponding element to italics.

font-family

font-size

font-weight

font-style

Specifies some additional text decoration to the corresponding element. Values text-decoration allowed are: none (this removes all text decoration), line-through (this draws a line through the text) and underline (underlines the text). Specifies a height of a line for an element. There are several possible measurement values you can use, listed in table 2.6 (for example: ...{line-height: 5cm; ...} makes the height of each line for the specified element 5 centimeters. Extra spacing (unused spacing) is placed before lines.

line-height

background

Specifies a background color or image. There are a few ways to specify background colors and images. You can specify a color name (for example: {... background: forestgreen...}; you can specify a color using a hexadecimal value (for example:{...background: #FF00CC...} or you can specify a URL to an image (for example: {...background URL(http://myimage.com/imag.gif);...} note that the location of the image is surrounded in brackets. You can specify multiple values for this property. For instance, if the specified background does not exist, then you can use a background color (...{background: url(http://www.grfics.com/pic.gif) seagreen} specifies to use the bakground image pic.gif and use the background color seagreen. Specifies the length of the left margin for the specified element. The value in the length can be any of the measurements listed in table 2.12 (for example: {el] {margin-left: 10in;...}) sets the left margin at 10 inches. Specifies the length of the right margin for the specified element. The value in the length can be any of the measurements listed in table 2.12 (for example: {el] {margin-right: 10in;...}) sets the right margin at 10 inches. Sets the indentation for each paragraph for the specified element, when the specified element's tag is used in the document to begin a paragraph block. Sets the alignment for the specified element. Valid values are: left, center and right. Specifies the color of the text that is encapsulated by the element's tag. The color can be a color name or a hexadecimal #RRGGBB value (see Appendix B for a valid list of color names), values are specified in the same manner as the background property.

margin-left

margin-right

text-indent text-align

color

The abbreviations in Table 2.12 are appended to the end of a size specified for several of the properties of Table 2.11. For instance: the property margin-right can use any of the measurements listed below, all that is needed in the length with the abbreviation appended to the end of the length (for example, magin-left: 5in would be 5 inches for the left margin). Table 2.12 Measurement Sizes Used with Different Properties of Style Sheets Measurement Name Abbreviation Description Points Pixels Centimeters Inches pt px cm in Points are a measurement of font size. The default font on a web page is 10pt12pt. Pixels are a measurement of screen pixels. Pixels are relatively small compared to the other units. Centimeters are 1/100 of a meter (.39 of an inch). Inches are a United States standard measurement (1/12 of a foot, 2.5 centimeters)

In addition to the properties listed in table 2.11, there is also the font property which is used for specifying several properties for a font at once. The general syntax for specifying many different values of style for the font property is: ...{font: italic bold font size/line height fonts; ...} The values font and italic for this property are literal. You use them to specify whether the font is italic, bold or both (if both are specified). The "font size" section is used in specifying the size of the font in the same way as the font-size property and the "line height" section is used in specifying the height of each line, exactly like the line-height property (the "/" in the syntax does separate the two values; for example: 12pt/14pt specifies a font size of 12 pt and a line height of 14pt). The "fonts" section is used is used in specifying a font to use and alternative fonts to use, the same way as the font-family property (multiple fonts are separated by columns and should be in quotations: for example: "Arial, Times, Symbol"). These properties should be used in the same order as indicated in the syntax or the current implementation of this property may exhibit some strange behavior (like add additional line spacing). Here's a full example: P {font: bold italic 12tp/18pt Times} In this example, we used the font property for the P element. We set both the bold and italic attributes, we made the font soze 12pt and the line height 18pt. We specified one font: Times. Style Sheets and Base Attributes A brief mention of base attributes where mentioned in a prior section. One of their major applications, besides Visual Basic Script is style sheets. For complex documents that required many different fonts and styles (an E-zine, for instance) you can use the system of classes in an HTML document to conveniently use multiple styles for a tag specified in the <STYLE> section. Additionally you can use the ID/NAME tag to reference different styles you have defined. The method for accomplishing both of these are listed in the next sections.
Using Style Sheets and the CLASS attribute

You understand that the CLASS attribute is used inside an HTML tag, now, how do you use this attribute to have many defined styles for the same tag? The method is simple. You append a . with a class name of your choosing to the end of the TAGNAME portion of a style definition for an element. Now, using the corresponding tag in an HTML document, you can use the style you specified for that tag if you set the CLASS attribute of that tag equal to the name you chose (without the .). For example: <HEAD>

... <STYLE> A.weird {text.decoration: none; color: navajowhite} </STYLE> </HEAD> <BODY> <A HREF="http://www.someplacefaraway.com/" CLASS="weird"> ... </BODY> In this example, we chose to give the A element a certain style. We also assigned this style definition a class: weird. When we want to use the style defined by the weird class for the A element, we just call that class name from the corresponding tag in the body portion of the document.

Remember: a tag is an element with the "<" and ">" brackets surrounding it.

When you are using the CLASS attribute with HTML for style sheets, you must have a must have a class specified for the tag you are using (for example, if you had the element B which was part of the class "test", you could not use this class with the <A> tag unless you had a style specified for the A element in the "test" class). Now, to use different defined styles for the same tag, you just append a different class name to the element in the <STYLE> section and call that class from your respective tag in the body of your document. For example: ...

<HEAD> ... <STYLE> A.foo {text-decoration:none; color: hotpink} A.bar {color: gray; font-size: 14pt} </STYLE> </HEAD> <BODY> <A CLASS="foo" HREF="http://www.rt66.com/iymalluf/">Go to the MCS [ccc] Web site</A><BR> <A CLASS="bar" HREF="http://www.microsoft.com">The Microsoft Web site</A><BR> <A HREF="http://www.farawayforgottenland.ffl">This goes nowhere</ A><BR> ... Note in this snippet code that there are two classes used in the style section: "foo" and "bar". The A element is used in both these classes and the first two <A> tags in the body references those classes. Note that the third <A> tag there is no class specified. It uses the default style. If there was a style specified for just the <A> tag then that style would be used if the tag did not use any class.

The A element, when used in style sheets, has to "pseudo-classes" which are used to set the different styles of a visited link and unvisited link. These are: A:link and A:vlink and all the properties for each "pseudo-class" are specified in the same manner as the normal syntax (for example: a:link {color: red} and A:vlink {font-size:12in}).

Using the ID/NAME Attributes and Style Sheets

You can also use the ID/NAME attribute with HTML tags to use a particular style you have define. Normally, you would define styles with an element preceding a set of curly braces which contain all the properties to that element. Now, instead of specifying a styles for a specific element, you can specify these styles for a name that you choose (the name must be preceded by the # sign). You then reference this name from your tags with the ID attribute. This tag then has all the styles that you specified for that name in the <STYLE> section. For instance:

... <STYLE> #mystyle {color:pink; background: aliceblue; font-size: 4in} ... </STYLE> ... <BODY> <P ID="mystyle"> Hi!! I should have a pink background and I should be [ccc] pretty large</P> ... In this example, we chose the name: mystyle and gave it a few properties shown. Then, from the body of the document, we used the <P> tag to call this style. We set the ID attribute of the <P> tag to "mystyle" which is where we have defined our styles for this particular name. When calling the name from your tags, you do not use the number sign. You can use this method for any element, but it would not be a good idea to use it with the <A> tag or other tags which need the ID attribute. For their case, it is safer to use classes or just define styles for those tags. HTML Tags Used with Style Sheets This section covers two tags and an additional attribute which change the style of HTML tags in a different document. There are two tags: the <DIV> and <SPAN> tags which allow one to encapsulate a block of text or other tags and apply a style to them. The STYLE attribute, which can be used in any tag is also capable of setting different styles for the text that tag encapsulates (effective in tags which render text somehow).
The STYLE Attribute

The STYLE attribute, as previously mentioned, is capable of setting many style properties for the tag that it is used in. The text that tag encapsulates then receives those styles. The values for the STYLE attribute are the different style properties mentioned in table 2.12 and their values with each property separated by a semicolon (for example: STLYE="color: blue; font-size: 30px; ..."). The STYLE attribute is a simple way to give bits and pieces of your text different styles if want explicit styles to exist, or if you feel no need for defining multiple styles for several elements.

The <DIV> and <SPAN> Tags

The <DIV> and <SPAN> tags, which are very similar to each other, are used to encapsulate blocks of text and tags and apply a style to them. This could be tediously accomplished with the STYLE tag, but these tags make it easier. The <DIV> Tag The <DIV> tag is used to divide of sections of the document and apply a style too that section. Consider the use for this tag. Maybe you have a set of pre-defined styles in the page. Maybe you are quoting some one's work as reference and you want that section of your document to be italicized and also have an inch more of margin space on the right and left sides. All you would have to do is simply encapsulated the entire cited text with the <DIV> and </DIV> tags. Then you use the STYLE attribute and set the properties for spacing and italics: ... <DIV STYLE=" left-margin: 1.0in; right margin: 1.0in; font-style: italics "> ...This is my reference material ... </DIV> In this example, we set the left-margin, right-margin and font-style attributes. Whatever text that is encapsulated by this tag inherits the properties specified by this tag. Style sheets also work by inheritance (refer to the Nesting and Inheritance section for more information). The <DIV> tag can also use classes and the ID attribute for defining its own style in the style section as well. You would put the DIV element in a class the same way you would any other element: append the name of a class you choose (with the .) to the end of the DIV element in the style section with the properties you specify. DIV.ref {line-height: 12pt; background: moccasin} The previous example uses the class "ref" for the DIV element. To use the styles specified for this element, all you would do is add the attribute CLASS="ref" in the <DIV> tag you want. The ID attribute also works the same as for other tags. The <SPAN> tag There is virtually no difference between the <SPAN> tag and the <DIV> tag. Their syntax is the same and more of a logical difference exists. The <DIV> tag is used to divide sections and render them with different styles, whereas the <SPAN> tag is used to span of portions of text and render them different styles. As in the <DIV> tag, you can also use the STYLE, CLASS and ID attributes in the same manner.

Inheritance and Nesting with Style Sheets Inheritance is also allowed with style sheets, and inheritance for frame sets and tables functions the same as style sheets. You can also control the styles of nested tags with style sheets.
Inheritance

When tags are nested in other tags which have a style specified, these nested tags also inherit that style. For instance: ... P {font-size: 3in} ... </STYLE> <BODY> ... <P>This text is 4 inches tall. <A HREF="http://www.nm.org">This is a link to some where </A></P> ... In this example, we gave a style to the P element and in the body, we put an anchor (<A>) tag inside the <P> tag. Notice in Figure 2.8 that the text in the anchor is the same size as the rest of the text but is still blue and underlined. Why? No properties where specified for color and text-decoration so the tag retains them. This rule holds true for all elements. FIG. 2.8 This figure demonstrates how nested tags are affected by styles assigned to their parent tag (or the tag that encapsulates the nested tag).
Styles for Nested Tags

It is possible to specify styles for different instances of nested tags. For instance, if you have an <A> tag nested inside an <H3> tag, you can set the properties for the A element when that "nesting" occurs. The syntax is quite simple. All one does is place the element that is to be nested after the element it is to be nested in (these elements should be separated by a space). When the nested tag specified is nested, then it will use the styles defined by it in the style section of your document. For example: <STYLE> ... H3 {color: forestgreen}

H3 A {color: #00CC00} ... </STYLE> </HEAD> <BODY> ... <A HREF="http://none.com">This is a normal link</A> <H3> Some text in a level-3 head, <A HREF="http://www.where.com">A link, that is a different color because [ccc] it is nested. </A></H3> ... We specified styles (a color) for the H3 element in the style section. Right after the style definition for the H3 element, we defined a style for the A tag if it is nested in the <H3> element. So when one uses this style, all the <A> tags nested (or encapsulated) inside <H3> tags will be rendered in a darkmedium blue. All other <A> tags will be rendered normal unless they are encapsulated in other tags that have different default or defined styles.

Many elements can be nested when specifying different styles. For example: UL UL A {color: red} This example indicates that an anchor tag nested in an unordered list which is nested in another unordered list is given the color red.

An Example Usage of Style Sheets In this section, an example of style sheets will be demonstrated. All the style properties and the methods for implementing them will be used to creatively design a page. Note how the styles are used to create an interesting page. The file stylescool.htm is in Listing 2.13 and can be found on the accompanying CD as stylescool.htm. Figure 2.9 illustrates this listing. Listing 2.13 STYLESCOOL.HTMAn Elaborate Usage of Style Sheets <HTML><HEAD><TITLE> A neato demonstration using style sheets... It's cooler than you</TITLE> <STYLE>

BODY { background: wheat } TABLE.forest { background: URL(new33.gif) gold; color: lime; text-align: center; margin-left: 0in; margin-right: 0in } TD.firstb { background: goldenrod; text-align: left; color: black } #newhead { color: blue; font-size: 18pt } #small { font-size:8pt; color: blue; font-family: Helvetica; text-align: right; line-height: 8pt } P.subhead { margin-left: 20px; text-align: left; background: forestgreen } SPAN.head1 { font-family: Arial Black; color: midnightblue; font-size: 14pt } P { text-indent: 0.25in; margin-right: 1.0in; margin-left: 5px; line-height: 0.20in } EM { color: red; font-style: none; font-weight: bold

} STRONG { font-family: script; font-weight: normal; color: green; font-size: 18pt; text-align: right; line-height: 18in; } UL LI { color: blue; margin-left: 0.25in; } UL UL LI { color: slateblue; } DFN { font-style: normal; background: lime; font-style: none } A:link { color: honeydew; text-decoration: none } </STYLE> </HEAD> <BODY TOPMARGIN="0" LEFTMARGIN="0"> <TABLE CLASS="forest" WIDTH="100%" HEIGHT="65%"> <TR><TD COLSPAN=2> <HR> <P ID="small">WELCOME TO. . .</P> <NOBR> <SPAN STYLE="color:#00FF00; font-size:100px">F</SPAN> <SPAN STYLE="color:#00EE00; font-size:99px">O</SPAN> <SPAN STYLE="color:#00DD00; font-size:98px">R</SPAN> <SPAN STYLE="color:#00CC00; font-size:96px">E</SPAN> <SPAN STYLE="color:#00BB00; font-size:97px">S</SPAN> <SPAN STYLE="color:#00AA00; font-size:95px">T</SPAN> <SPAN STYLE="color:#00BB00; font-size:100px">G</SPAN> <SPAN STYLE="color:#00CC00; font-size:100px">R</SPAN> <SPAN STYLE="color:#00DD00; font-size:100px">E</SPAN> <SPAN STYLE="color:#00EE00; font-size:100px">E</SPAN> <SPAN STYLE="color:#00FF00; font-size:100px">N</SPAN></NOBR> <HR> <P CLASS="subhead">An electronic magazine for everybody,

including vindictive [ccc] vegetable heads and mucky meatball morsels.</P> </TD></TR> <TR> <TD WIDTH="100%" CLASS="firstb"> <SPAN CLASS="head1">Our first issue!</SPAN><BR> <P> Welcome to our premiere edition of FG. We are proud to have it up. We are sad to say, however, that our feature article will not be available because we have nothing to say. So we are writing this apology, hoping you will read our news letter next week. We will have 2 times as much next week. We <EM>PROMISE</EM>! <BR> -<STRONG>The Editorial Staff</STRONG></P> <P>Actually, this is just a demonstration on how to use style sheets, and some of the many different elements involved in making style sheets. You can add nice headings with out a whole bunch of font tags, you can also <DFN>highlight</DFN> certain portions of your text by assigning a background property to an element you choose in the stylesection and then using the corresponding tag (the element you chose with the &quot;&lt; &quot; and &quot;&gt;&quot; brackets).</P> <P>Below is a link:<BR> <A HREF="http://www.microsoft.com"> When you click on this link, you will go some where</A>. It is not underlined. This is done with style sheets as well.</P> <HR> <SPAN CLASS="head1">New Garden Tips</SPAN><BR> <P>Peter Planter divulges some of his best gardening tips, some of these [ccc] tips are: <UL> <LI>Never water your plants when it is raining</LI> <LI>Don't put turtles in your garden.</LI> <UL> <LI>This is <EM>never</EM> a good Idea!</LI>

<LI>Really, take it from experience!</LI> </UL> <LI>Nature controls how your garden turns out</LI> </UL> </P> <HR> <SPAN CLASS="head1">More Stuff Soon!</SPAN> </TD></TR></TABLE></BODY></HTML> FIG. 2.9 This figure illustrates Listing 2.13. This figure illustrates an extensive use of style sheets. Most of the entities of style sheets mentioned are used in Listing 2.13.

It is not necessary to have all the properties for an element immediately follow one another when specifying multiple properties for an element in the styles section of a document. It might be more helpful to organize them as shown in (the previous listing). With this method, you put each of your properties on a separate line and place them after the curly braces to indicated that these properties belong to the specified element; the properties are more organized and you can clearly spot errors when this method is used.

Emerging HTML Standards


HTML is a continually evolving language, not only because the standards committees often introduce new drafts and ideas, but because the commercial producers also extend with their own proprietary extensions that are sometimes incorporated into HTML. The HTML 2.0 Document Definition Type, or DTD, is currently in the phase of final review and should become a standard pretty soon. While this final review is going on, it seems as if the standard for the HTML 3.0 DTD is swiftly on its way, but there are several tags and elements that are still under heated discussion. The new entities of HTML that are in the spotlight now are, of course, client-side scripting capabilities, the usage and standards of objects, client-side image maps, ways to represent mathematical expressions and equations, client-drawn figures, and style sheets. Some of these HTML components are pretty stable and only minor syntax is being discussed. However, other tags and elements of the HTML language are still in the midst of intense discussions. Style sheets and their usage in HTML will be very effective once fully implemented. Style sheets give the author the ability to create a set of documents using a certain style. This style includes a method of defining different colors and fonts to form a particular feel for the document. Style sheets,

according to the current specification, can be separate files and can be imported at will. There can also be multiple style sheets based on different MIME types such as RTF. Particular styles can also be spanned to affect a specified portion of text in an HTML document. Again, this is still under heavy discussion so the information mentioned here is likely to change. As you can see, objects and scripting are more mature , in development and implementation , than style sheets. Of course, the first implementation of style sheets with Internet Explorer 3.0 beta 1 is pretty impressive, even though only a handful of the proposed properties are supported. Object models and scripting capabilities have already been supported by major browsers such as the Microsoft Internet Explorer and Netscape Navigator, but Internet Explorer can boast one of the more complete implementations of style sheets. Mathematical representation and client-drawn figures are still in the early stages of development, and will probably make significant progress in the second or third quarter of 1996. We have talked about the emerging standards of HTML and how they will affect future versions of HTML, but now let's examine and compare what makes it possible for us to utilize HTML: the Web servers and browsers. ON THE WEB The W3C (World Wide Web Consortium) has practically all the documentation available for standards and works in progress on HTML, objects, MIME types, and other standards related to HTML. Their Web site is located at http://www.w3.org/.

Internet Browsers and Servers


This section contains a brief comparison of the leading browsers and servers, and their advantages and disadvantages. This comparison involves Microsoft-based operating systems, since that is the only place where Visual Basic Script is implemented. First, we compare Web browsers in functionality and performance, then we compare Web servers in the same fields. This is not a benchmark comparison or any formal comparison, but more of a general comparison based on use and preference. The three major browsers, it is fair to say, are the Microsoft Internet Explorer, Mosaic (and all variations), and Netscape Navigator. Internet Explorer is easily the latter of the two, but still it has many advantages. Also, it ties in with both JavaScript and Visual Basic Script, has support for tables and frames, works well with the ActiveX controls, and is free. Plus, Microsoft's Web site is easy to navigate through and is very simple to find information for the consumer and the author. Netscape has very good support for JavaScript and most of the HTML support previously mentioned, but there seems to be no direct support for ActiveX or Visual Basic Script. Also, it is not free. The pioneer Web browser, Mosaic, was developed primarily by the National Center for Supercomputing Applications (NCSA) at the University of Urbana-Champaign in Illinois. This browser does support some HTML 3.0 and has a nice Hotlist feature, but it lacks many of the newer functions including objects, frames, and script support. If you're for die-hard standards, then Mosaic is for you! ON THE WEB

There is a Netscape plug-in available which will allow you to use Visual Basic Script in Netscape. You can get this add-on at http://www.ncompasslabs.com/. The status of Web servers is similar to that of browsers. There are several free Web servers that are based on the UNIX NCSA or CERN models. These are somewhat powerful, easy to use, and provide pretty good support for CGI programs. Netscape Enterprise is a very powerful, yet very expensive, Web server that offers full support for Java and CGI programs; Netscape communications also has FastTrack server, which is more of a "desktop" server that can be used by individuals with small connections. Microsoft has the Internet Information Server (ISS), which is free and comes with Windows NT v4.0 Server, and is also available freely for Windows NT. It supports much of what Netscape supports, except JavaScript. IIS supports Visual Basic and works very smoothly with SQL databases. It's an excellent deal for the price. Microsoft also has Vermeer Front Page, which is its counterpart to Netscape's FastTrack server. Vermeer has a fairly decent editor and an excellent organizer, plus it allows extensions to many popular UNIX and PC servers. FrontPage, which is still a beta product, consists of an editor, an organizer, and a Web server, which can run on Windows 95 or NT Server/Workstation.

From Here...
In this chapter you have learned the fundamental workings of HTML. HTML is an unsophisticated "mark-up" language which is the primary method for communicating hypertext documents across the World Wide Web. Visual Basic Script is an "inline" scripting language which allows you to amplify the interactive content of your web pages. This chapter has helped you understand some of the basic concepts crucial to the use of Visual Basic Script, such as forms and other entities which complement Visual Basic Scripts ability to create truly dynamic web pages. Some of these complementary elements are tables, frame sets and style sheets. Also covered in this chapter is a brief discussion on the future of HTML and a brief overview of the leading Internet browsers and Web servers. In subsequent chapters, you learn the different functions and methods of Visual Basic Script. Check out the following chapters:
q

Chapter 3, "Introducing the ActiveX Control Pad," provides an excellent overview of how to use the ActiveX control pad: a tool for making your documents very interactive. Chapter 12, "A Sample VBScript Page," takes close look at other entities which are crucial to designing Visual Basic Script applications such as the ActiveX controls, the Internet Explorer 3.0 object model, and the ActiveX control Pad. For a general explanation of VBScript and examples, see Chapter 13, "Comparing VBScript, VBA, and Visual Basic." The different data types, structures, and variables VBScript supports are covered in Chapter 15, "VBScript Data Types, Variables, and Structures."

| Previous Chapter | Next Chapter |

| Table of Contents | Book Home Page | Buy This Book |


| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 3 - Introducing the ActiveX Control Pad & Layout Control


by Ibrahim Malluf

In this chapter
q q

q q q q

q q

Exactly what the ActiveX Control Pad is ActiveX Control Pad is a complete VBScript or JavaScript editor, as well as an ActiveX Control editing tool. ActiveX Control Pad as an editing environment ActiveX Control Pad is an excellent tool for learning VBScript and the Explorer object model. The ActiveX Control Pad's use of the Layout Form ActiveX Control Pad's central theme, the Layout Form, gives incredible drop-in-place capabilities for HTML document development. Animated Demonstration Build an animated demonstration of the ActiveX Chart control using the Layout control as the container.

When the ActiveX Control Pad was released, almost no one in the development community knew it was comming. We all knew that the VBScript development tools at the time were limited to NotePad or some other text editor. Ron and I were even working on the beginnings of a limited IDE to include with th book. The ActiveX Control Pad completely changed all of that. Enthusiastic?, you bet !

The ActiveX Control Pad's IDE


The first impression you get of the ActiveX Control Pad is that it is a really cool environment for placing ActiveX controls on a form, visually aligning them, and manipulating their properties. As you dig deeper and play with the Script Wizard, you find that you haveaccess to all of the Explorer's object properties and methods, access to all of the added control properties and methods, and, finally, the ability to add and edit user-defined procedures and variablesall within the Script Wizard. You come to the realization that the ActiveX Control Pad is actually a complete VBScript or JavaScript editor, as well as an ActiveX Control editing tool. Some serious limitations and a few bugs exist in

the beta product we are writing about here, but expect the ActiveX Control Pad to be much more robust and stable by the time you read this book.

The MDI Interface


The first thing that greets you when you load the ActiveX Control Pad is a Multiple Document Interface (MDI) setup with the usual menu bar, tool bar, and status bar (see fig. 3.1). The right mouse button calls a pop-up menu that gives access to the ActiveX Control Pad's features, depending on your current context. The ActiveX Control Pad adheres to the Windows 95 standard interface for MDI applications. FIG. 3.1 Open the ActiveX Control Pad for the first time.

The Document Window


A child form containing a document window titled Page1 is open waiting for you input. This document window is a direct edit window for HTML documents, complete with a skeletal outline of HTML tags (refer to fig. 3.1). You can load any HTML page into ActiveX Control Pad and begin editing it. Down the left side of the edit window a gray vertical bar serves as a container for miniicons that indicate the placement of Controls, Script, and Layout Forms (see fig. 3.2). FIG. 3.2 Look at the mini icons in the Document Window. These icons will bring up the appropriate object editor when you click a left mouse button on them. Clicking the script icon brings up the Script Wizard; clicking a control icon brings up the ActiveX control editor. Figure 3.3 shows the ActiveX Control Pad with a label control in edit mode and the resulting Web page with that label in an Explorer 3.0 window.

Direct Placement of ActiveX Controls


Limited Placement
The placement of ActiveX controls directly on a Web page is limited to the peculiarities of the Web design. You cannot exactly place a control in terms of its Top or Left properties but are limited to the Right, Center, Left type of placement commands that HTML provides. You can create tables and place controls within those tables for a greater degree of control over where they will appear, but theplacement limitations are still there.

Ideal Editing Environment for Controls

Prior to the availability of the ActiveX Control Pad, placing of ActiveX controls in your document involved getting the CLSID of the object from the Registry, placing it into the Object Tag, remembering all of the relevant properties of the control that you needed to modify, and finally remembering or otherwise finding out what event or methods were available for the control. It was very tedious work. The ActiveX Control Pad puts all of this behind with an almost ideal environment for placing and editing ActiveX controls in your document. In Figure 3.3, you can see the Edit Control window in the upper left. In the Edit Control window, you can visually size your control and directly edit some properties; in the label's case, you can edit the caption property. On the left side of Figure 3.3 is the Properties window. If you have ever worked with Visual Basic, this window is quite familiar. It provides a list of all the editable properties for the selected control. You can edit those properties right in the Properties window. Once you have your properties set and the control sized the way you want it, you close the control's Edit window and the resultant HTML code is placed into the document you are editing. FIG. 3.3 Edit an ActiveX label control with the ActiveX Control Pad. The code that the ActiveX Control Pad inserted into our document for our example label is shown in Listing 3.1. As mentioned earlier, in the beta version of Explorer 3.0, the only way to insert an ActiveX object into the document was to extract the CLSID number from the Windows registry by looking it up with a utility like Regedit. The ActiveX Control Pad eliminates this entirely.

Listing 3.1 CHAPER3_1.HTMLThe ActiveX Control HTML code inserted by the ActiveX Control Pad <OBJECT ID="Label1" WIDTH=445 HEIGHT=49 CLASSID="CLSID:978C9E23-D4B0-11CE-BF2D-00AA003F40D0"> <PARAM NAME="BackColor" VALUE="2147483653"> <PARAM NAME="VariousPropertyBits" VALUE="8388627"> <PARAM NAME="Caption" VALUE="The ActiveX Control Pad"> <PARAM NAME="Size" VALUE="11783;1305"> <PARAM NAME="FontName" VALUE="Matura MT Script Capitals"> <PARAM NAME="FontEffects" VALUE="1073741825"> <PARAM NAME="FontHeight" VALUE="480"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="700"> </OBJECT>

When directly working with ActiveX controls on the HTML document as shown in this chapter, you simply choose the Insert ActiveX Control from the edit menu or from the pop-up menu when rightclicking the mouse button. A dialog box, as shown in Figure 3.4, pops up and lets you select from a list of all available ActiveX controls on your system. Just click on the desired control and it is automatically inserted into your document including the required CLSID number. FIG. 3.4 Select an ActiveX Control to insert directly into an HTML document.

At the time of writing this book, Explorer 3.0 Beta 1 did not have the licensing mechanism in place. So many ActiveX controls, while functional in a development environment would not work in a Web page. Only the controls that actually shipped with ActiveX Control Pad were guaranteed to work. Microsoft said that this issue would be resolved by the time Explorer 3.0 is a shipping product. Part of this solution will include a limitation on what controls you can use based upon those licensing requirements.

In Figure 3.4, you can see that a command button is about to be selected from the controls list dialog. The command button will be used to add some user interaction to the demo page. The command button is added to the project having its name property changed to btnStartStop. After going through the drill of setting properties, sizing the button, and so on, the edit window is closed and the script behind the button is entered into the button's click event.

Limited Script Editing Environment


By right-clicking the mouse on the HTML document on the desired insertion point, the pop-up menu allows the selection of the Script Wizard as shown in Figure 3.5. FIG. 3.5 The Script Wizard opened to the btnStopStart Command button's click event procedure. The ActiveX Control Pad's Script Wizard provides an editing environment that gives easy access to all events, procedures, properties, and methods of the Layout control and all other controls and scripts contained within the Layout Control. Figure 3.5 shows the Script Edit window open to the click event of the Command button that was added to the HTML document. I want to cause Label1's forecolor to change every time the button is clicked to a randomly selected color. Looking again at Figure 3.5, in the right side list box labeled 2. Insert Actions, select the Label1's forecolor property by double-

clicking it. It will be automatically inserted into the button's click event script. Complete the script by adding the code in Listing 3.2 to generate a random number. Finally finish by closing the Script Wizard's window. The VBScript code is automatically inserted into the HTML document.

Listing 3.2 CHAP3_01.HTMThe Click Event Code Is Inserted by the Script Wizard Sub btnStartStop_Click() Label1.ForeColor = int(65534) *rnd + 1 end sub The Script Wizard can work with either VBScript or Java Script. But the Wizard, as it stands now, cannot work with a document that is using both. It's a one-or-the-other proposition. The Script Wizard's List View provides an alternative method to writing VBScript. By selecting List View, you can have the Script Wizard insert code into events for you using dialog boxes based on the action you select from the Insert Actions list. As an example, let's have Label1's caption change to This is a Test when clicking the mouse button on it it and have the caption return to ActiveX Control Pad when letting the mouse button back up. To do this select the MouseDown event in the Event window as the event where the code will be inserted. Select Label1.Caption in the Select Action window. The dialog shown in Figure 3.6 illustrates how to add the changed caption to the MouseDown event. The Script Wizard will present any one of a number of different dialogs based on the action selected. In this case, selecting the caption action means that I want to add a different text to the caption, so a text entry dialog is presented. FIG. 3.6 Use the Script Wizard in List View Mode to add code to the MouseDown event of a label. The Script Wizard is a great aid to writing event event driven script that holds your hand when needed and easily gets out of the way when you want to do things your way. Since the ActiveX Control Pad is an MDI application, you can have several Web page documents open at one time. You can have several Layout Forms open as well. "What are Layout Forms?," you ask? Just continue reading to find out about one of the most innovative improvements to HTML Web pages to come down the information highway.

The Layout Form: An Object to Contain Your Objects


The HTML document, as it stands today, allows you to place many different types of objects on a browser's screen but imposes a very strict set of placement rules that can make designing Web pages

very frustrating at times. How often have you wished to be able to precisely place a graphic, input box, or even text in anexact spot on your page, or how about the ability to place overlapping graphics and controls? Well this ability, along with a few other, eye-opening advancements, is now available through the auspices of The ActiveX Layout Control. (For Visual Basic programmers, the closest analogy to the Layout Control is a Visual Basic Form's client area. You have this sizable form that allows you to place your text and controls precisely where you want them with none of the restrictions imposed by HTML pages.) From the File menu or the right-click pop-up menu, select Insert New Layout Control. A dialog pops up asking for a file name for the new Layout control. Enter Chap3_02 for the name of the Layout control file as shown in Figure 3.7. FIG. 3.7 Insert a new Layout control into a Web page.

While the example that I am developing here is specifically intended for insertion into a particular page, I should mention that you can create or edit a Layout control without making it part of a Web page document. By selecting New Layout Control from the Files menu, you can set up a new Layout control without any associated Web Pages.

Continuing on with this example, you can see in Figure 3.8 a Layout Control open in edit mode, along with a Toolbar containing available ActiveX controls. As mentioned earlier, the Layout Control appears exactly like a Visual Basic form, But unlike a Visual Basic form, only the client area of the form is visible when displayed on a Web page document. FIG. 3.8 The Layout control and toolbar are ready for editing.

Modifying the Toolbar


The Toolbar gives you a selection of ActiveX controls that you can add to your Layout Control very simply. Select an ActiveX control on the Toolbar by left-clicking the mouse pointer on the ActiveX control desired. You can then draw the control on the form by moving the mouse pointer to Layout Control's client area and drawing the control while holding down the left mouse button. The list of available ActiveX controls can be easily added to by right-clicking The Mouse on the Toolbar; a dialog (as shown in fig. 3.9) pops up allowing you to choose the controls to add to your oolbar. In fact the toolbar is a fascinating expansion of the original Visual Basic toolbar. The ActiveX control

toolbar allows you to arrange groups of controls on different pages. FIG. 3.9 Use this dialog window for adding ActiveX controls to the toolbar. To add controls to or delete controls from a particular page, make the page the active one, right-click that page, then add or delete controls using the pop-up menu's selections. You can add pages to the toolbar by right-clicking one of the tabs to get a pop-up menu allowing you to add or delete pages. The menu also allows you to rename the page's tabs or change the order of the tabs. But here's the real kicker: you can export or import toolbar pages! Imagine having a set of custom controls relevant to a particular project assembled on one toolbar page. Now if you have several of these pages, you can load or unload depending on what is needed for the project you are working on.

Adding Controls
Going back to the project at hand, I can begin to add some controls and then add some VBScript to round out the example project for this chapter. Let's say that the assignment is to create a demonstration of the Chart ActiveX control that can be dropped on any HTML document. The Chart ActiveX control has several different chart types that should have a method that makes it easy to switch back and forth between the different types. In this case a TabStrip is used as an easy way to select the viewing of the different chart types. After adding the TabStrip, add several tabs, one for each chart type that is going to be displayed using the pop-up menu shown in Figure 3.10. To get at this menu, you have to get the tab strip to change into Tabselect mode by left-clicking the left mouse button on a tab. When the tab you are clicking on gets the focus (noticeable by the tab's caption being outlined), right-click the mouse and the pop-up menu in Figure 3.10 will show. FIG. 3.10 Here's the Pop-up menu for adding tabs to the TabStrip.

I had trouble getting this to work consistently and attribute it to the still shaky interface code of the Beta product. I expect that it will have improved responsiveness by the time this book is printed. If you are still working with the Beta release, be patient with some of these interface problems and retry some of these things until they do work for you.

In this example, 21 tabs were added to the control, then for each tab select Rename from the tab's popup menu and add the Chart type name to the tab that correspond's to the Chart control's Chart type

(such as Tab 0 = 0-Simple Pie Chart, Tab 1 = 1-Special Pie chart, and so on), until all of the chart types are entered into the tab control. Then Iput an ActiveX Chart control into the layout as shown in Figure 3.11. add an ActiveX IELabel control to the Layout Form to complete the example layout. Later in the chapter I will flesh out the example Layout Control with some code. FIG. 3.11 Here's the Layout control with the Chart control and Label control added to it.

Creating Drop-in-Place Interfaces


The Layout Control at the time of writing this book was a separate item that had to be downloaded by the IE30 Beta 1 browser. According to Microsoft, the release version of Internet Explorer 3.0 will incorporate the Layout Control so that it will not have to be downloaded. The code for the Layout Control is presently contained in a separate .ALX file that is downloaded by your Web document during runtime. My understanding is that as soon as the W3C approves and adopts the new initiatives presented by Microsoft, the Layout Control's code will be able to be within the Web document itself. In any case, the Layout Control lends itself to the development of drop-in-place interface elements such as navigational bars, data input forms, data display, and other operations that can be easily encapsulated.

Building a Layout Control Application


The application I develop in this section demonstrates the different capabilities of ActiveX Chart Control, which comes with the ActiveX Control Pad. In this section we'll use the Script Wizard to build the underlying code that will control the ActiveX Chart control demo.

Selecting Different Chart Views Using the Tab Strip


In this example the tab strip has 21 tabs, each named after a chart type in the Chart control's properties. Conveniently, the chart types are designated by numbers, so Ican make each tab correspond to a chart type number. Right-clicking to bring up the Script Wizard as shown in Figure 3.12, we choose the change event of the tab strip (ID=tabChart) and add the code shown in Listing 13.3. FIG. 3.12 Select the Change Event of the TabStrip from the Script Wizard.

Listing 3.3 CHAP3_02.ALXChanging the Chart Type Displayed According to the Selected Tab

Index Sub tabCharts_Change() 'change the cart type according to the 'tab index of the selected item iechart1.ChartType = tabCharts.SelectedItem.Index End Sub This single line of code in the tabCharts_Change eventcauses the chart types to change with each change of a tab.

If you are considering using the the click event,instead of the change event I should warn you that in a multi-row tab control the click event will not show a change to the tab you clicked on if there was a row change. Even though the focus ring in the tab changes to the tab you clickedon, the actual focus will not change. You have to click on the tab a second time to cause an actual shift of focus to the desired tab. Using the change event avoids this problem.

With this much completed, save the Layout Control and call up the page containing it in Explorer. The user should be able to go through each chart type, as shown in Figure 3.13.You could leave it at that and have the demo completed, but many of the different chart views will not be showing their best view with the default data contained in the chart control. There might also be a desire to have a different look every time tabs are changed. Let's start by adding a procedure that will add a random number of rows and columns. Calling up the Script Wizard, Iright-click the mouse pointer on Procedures in the Insert Actions list, and a pop-up menu allows you to select New Procedure. The procedure window shows a sub named Procedure1. Since the procedure is supposed to return a value a function procedure is wanted instead of the Sub type procedure. Change the sub to function while also changing the name of the procedure to RandomNumber. In this edit window, note that the procedure declaration area is entered by clicking the mouse pointer on the declaration line. You also need to click the mouse pointer into the procedure body area to edit the script after you have edited the name and type of the procedure. There were no shortcut keys that I could find letting me jump from one area to another in the editor. The Tab key didnn't work either. Going through the prototype help file also didn't reveal any shortcuts. Perhaps by the time the ActiveX Control pad has been released from beta, issues like this will have been addressed. Listing 3.4 shows the RandomNumber function along with the modified tabChart_Change event procedure utilizing the function.

Listing 3.4 CHAP3_02.ALXThe RandomNumber Function and the tabChart_Change Event Procedure Modified to Use the Function <SCRIPT LANGUAGE="VBScript"> <!-Function RandomNumber(MyLimit) 'firs make sure a number was passed If IsNumeric(MyLimit) Then 'returns random numbers RandomNumber= int(MyLimit)*rnd + 1 Else 'if a non-numric value then return 'a random number based on a fixed limit 'No need to have a code failure here RendomNumber = int(10)*rnd + 1 End If end function Sub tabCharts_Change() 'change the cart type according to the 'tab index of the selected item iechart1.ChartType = tabCharts.SelectedItem.Index iechart1.Columns=RandomNumber(15) iechart1.Rows = RandomNumber(10) end sub --> </SCRIPT> The function takes a numeric argument that determines the upper range of the random number to be generated. Note that I first check the argument for being a numeric value with the IsNumeric() function. If it is not a numeric value, then the argument is ignored and a random number is generated that would be safe for all circumstances in this application. In this instance, keeping the script operational is more important than confronting the user with an error condition. When the user selects a chart type, it will present the chart in a different configuration every time.

Animating the Chart Demo


Am I satisfied yet? Not at all! I want the chart to have some timer-driven animation, so let's add an ieTimer object to the Layout control and set its Interval property to 3000, as shown in Figure 3.13. FIG. 3.13

Add a timer control to the chart demo Project. Create a procedure using the Script Wizard that iterates through all of the rows and columns of the chart controlsetting each row/column DataItem property to a new random value. This sub procedure will be called by the timer at the end of each interval. Listing 3.5 shows the code.

Listing 3.5 CHAP3_02.ALXThe ieTimer_Timer Event Calling the ColumnValues Procedure Sub IeTimer1_Timer() call ColumnValues() end sub Sub ColumnValues() Dim lngColCount Dim lngRowCount 'iterate through each row and column 'changing values For lngRowCount = 0 to iechart1.Rows -1 iechart1.RowIndex = lngRowCount For lngColCount = 0 to iechart1.Columns -1 iechart1.columnIndex = lngColCount iechart1.DataItem = RandomNumber(100) Next ' Next ' end sub The ColumnValues sub procedure changes all the DataItem values in the chart control every time it is called, using two simple nested For Next loops.

Accessing the Properties and Methods of the Layout Control from an HTML Document
Let's continue with this example program and write some VBScript in the HTML document that will manipulate the chart demo. Suppose Iwanted the demo to automatically change the chart types after a given period of inactivity. The way to do this would be to place a timer in the document that would count down a set period of inactivity and change the current tab in the Layout Control if it hasn't been changed by the user within that period of time. Right-click the Chap3_02.HTML Document and select the ieTimerCTRL from the control list. Then set the Interval to 3000 and Enabled to true and close the edit window for the control. Opening the Script Wizard, add four global variables and the code shown in Listing 3.6.

Listing 3.6 CHAP3_02.HTMThe Timer Event Code Used to Change the Displayed Chart Type <SCRIPT LANGUAGE="VBScript" On Load="InitALX"> <!-dim lngCurrentTab dim lngCountInterval dim lngLastTab dim lngCountDown Sub IeTimer1_Timer() lngCountInterval = 5 lngCurrentTab=ChartDemo.tabCharts.SelectedItem.Index 'check to see if the tab has changed 'since the last timer event If lngLastTab <> lngCurrentTab Then 'if it has changed then restart 'the countdown lngLastTab = lngCurrentTab lngCountDown = lngCountInterval Else 'if no changes then count down lngCountDown = lngCountDown - 1 End If If lngCountDown < 0 then 'move to the next tab if ingCurrentTab = _ ChartDemo.tabCharts.Tabs.Count -1 then 'we are at the last tab so 'start over lngLastTab=0 Else 'move to the next tab lngLastTab = lngCurrentTab + 1 End If 'here is where the tab is actually moved ChartDemo.tabCharts.SelectedItem.index _ =lngLastTab 'start the countdown over lngCountDown = lngCountInterval End If status = lngCountDown end sub -->

</SCRIPT> The code presented in Listing 3.6 is fairly straightforward. It first checks to see if the current tab index is different from the what it was in the previous timer event. If it is, then it restarts the countdown. If not, then it decrements the count contained in lngCountDown. When lngCountDown falls below 0, the tab is moved to the next available tab. If the last tab has been reached, it restarts at tab 0 and the whole process starts over again.

The Beta version of the Layout Control is usually loaded after the VBScript in the HTML document is parsed. This results in your VBScript code's references to the Layout Control to always fail. Microsoft's original position on this was that you would not be able to reference the properties and methods of the Layout control from your HTML document. But someone on the VBScript newslist discovered that by adding the OnLoad="InitALX" to the VBScript declaration tag you could indeed reference the Layout Control's properties and methods. Microsoft says that this won't be an issue in the released product. This caution is included just in case this is still a problem and you find yourself in the above described situation.

From Here...
The Chap_03.alx file can be dropped on any Web page document. The most convenient way to do this is to load your HTML document into the ActiveX Control Pad and select the Add Layout Control menu item from the Files menu or from the right-click pop-up menu. Later on in subsequent chapters there will be more examples of using the ActiveX Control Pad with ActiveX controls and VBScript to produce Some useful applications. This chapter introduces the ActiveX Control pad as the tool de jour for creating VBScript HTML pages. The Layout Control is also introduced here because of it's close relationship to the ActiveX Control pad. The Layout Control is not an integral part of the ActiveX Control Pad though, but an independant ActiveX Control that will be distributed as part of the ActiveX controls distributed with the Internet Explorer 3.0 browser. The Active X Control Pad and the Layout Control are used throughout this book to develop various approaches to Web page development. These chapters include:
q q

Chapter 11, "Designing VBScript Applications." Chapter 12, "A Simple VBScript Page."

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 4 - Creating a Standard HTML Page


by Ron Schwarz

This chapter covers the creation of "standard" HTML pages, using the ActiveX Control Pad. The word "standard" is in quotation marks, because even though these web pages only make use of scriptand control-enabled HTML (as opposed to HTML Layout Page features), the ActiveX Control Pad provides the opportunity to create pages that are anything but "standard" in appearance and function. And the ease with which these pages can be managed will enable you to focus on the task at hand, rather than get bogged down in the minutia of HTML. In this chapter, you use the ActiveX Control Pad to create a simple page, add a control, and enable it with a script. Throughout the example, you'll see references to objects, properties, code, and other programming language elements. Don't try to understand the guts of the language at this point they're fully described elsewhere in this book (check the "From Here" section at the end of this chapter for references to other chapters)the purpose of this chapter is to show you how to create a script-enabled HTML page using ActiveX controls, in a concise, step-by-step manner. In this chapter
q q q q q q q q q q

Essential HTML with the ActiveX Control Pad Use the ActiveX Control Pad to manage the creation of standard HTML pages. An Environment for Code Creation Use the features of the ActiveX Control Pad to go beyond simple text editing. Control Management Insert and manage controls with a mini-IDE. Event Code Management Automatically create event code skeletons. Script Management Automatically insert method and property calls; add non-event procedures.

Using the ActiveX Control Pad

The ActiveX Control Pad is sometimes called (in jest) Visual Notepad. If anything, it's Notepad on steroids. Its appearance is deceptively simple. When you first run it, you see what appears to be little more than a text editor. As with all decent software, its real power is under the hood. You're never more than a few mouse clicks away from features that will literally shave hours from the development time of any significant project. This little program is not to be underestimated, nor should the fact that Microsoft is giving it away at no cost be misconstrued to imply that it's of limited usefulness.

Starting the ActiveX Control Pad


Start the ActiveX Control Pad (see fig. 4.1), either by finding it in your Start Menu, or by navigating to it via Explorer or "My Computer." FIG. 4.1 This is the ActiveX control pad. Figure 4.1 shows the ActiveX Control Pad as it first appears when run. As you can see, it automatically creates a skeleton for your project, consisting of <HTML>, <HEAD>, <TITLE>, and <BODY> blocks. (The blank line in the <BODY> block is where you'll put your content.) It also creates a default filename of "Page1," and a default Title of "New Page". So far, so good. Now, for the good part. Let's say you want to put a Command Button on the page, and have it take the user to www.microsoft.com when it's clicked. You can do it the hard way, with lots of HTML, or, you can do it the easy way with an ActiveX control. The ActiveX Control Pad makes it extremely simple.

Inserting a Control
The first thing you need to do is insert the Button. To do this, bring up the context menu by clicking the mouse on the blank line. This puts the cursor at the position you want the control to appear. Now, move the mouse over the vertical gray area to the left of the editing area, and click its right button once. You'll then see a context menu like the one in Figure 4.2. FIG. 4.2 ActiveX control pad context menu. In Figure 4.2, the "Insert ActiveX Control" menu item is selected. Select it on your machine, and click. In a few seconds, you'll see the Insert ActiveX Control dialog. Find the entry for "Microsoft Forms 2 Command Button", as shown in Figure 4.3. FIG. 4.3

Insert ActiveX control dialog. Once you've selected the Command Button, either double-click its entry, or, click the "OK" button. Once you do that, you'll see two new windows floating over the Control Pad"Edit ActiveX Control", and "Properties", shown in Figure 4.4. If you've used VB before, things may be starting to appear familiar. FIG. 4.4 Control editing.

Setting Control Properties


The "Edit ActiveX Control" window contains what appears to be a small VB-style form, containing a single button control. It's not really a form, however. It's just a container to hold the prototype of the control, to provide you a context for editing purposes. When you're done editing, the control itself will be placed into the HTML on the page, without any trace of the "form." The other window (the "Properties" window) contains a list of properties and settings that apply to the control. From here, you can set starting properties that will determine the condition of the control when the page first loads. One advantage many of the ActiveX controls hold over their earlier VB counterparts is the ability to edit Caption and Text properties in-place. What the means is that you can type Button and Label captions right on the buttons, and TextBox text can be typed into the text. Other controls feature drag and drop capability too. To assign a caption to the button in this example, you can either locate its Caption property in the Properties window, or, you can enter it directly on the button. To enter it directly, click one time on the button, to bring the focus to the control. Then, wait a second or two. Then, click one more time. (The reason for the delay between clicks is to avoid sending a double-click.) As soon as you click the second time, you'll see a cursor appear in the center of the button. Type Go West!. As you type, the letters will appear one by one on the button. Because button captions are centered, the text will move to the left and right as you enter it, maintaining its centering. After you've finished entering the caption, your screen should look like the example in Figure 4.5. FIG. 4.5 Entering a caption.

Trying the Example

Click the Close button on the "Edit ActiveX Control" editing window (the small "x" in the upperright-hand corner of the window). This will return you to the ActiveX Control Pad's main HTML editing window, with the declaration for the button placed into the <BODY> block, as shown in Figure 4.6. FIG. 4.6 Viewing the updated HTML code. Notice the button that now appears in the gray area on the left of the editing window. You'll have one next to each embedded control on the page, and it's used for editing the control. Now, save the file by clicking the Save button (the toolbar button with a floppy disk icon). You'll be prompted to save "Page1.htm". Click the "Save" button to save the file. Once you've saved the file, run it by opening the folder it's in (or, browsing there with Explorer or "My Computer"), and double-clicking the "Page1" icon. After Internet Explorer runs, you'll see your page, which will look like the example in Figure 4.7. FIG. 4.7 Command button example in IE. Although you have a button on the page, if you click it, nothing will happen; you can't do anything with it until you add some code, which is explained in "Adding Event Code" later in this chapter.

Editing a Control
You've got a button on a page, but it's a bit large for its text, so, go back into the ActiveX Control panel, and click the button to the left of the Control declaration. You'll be taken back into control editing mode, which means you'll again have the control visible in its editing window, and the Properties window shown on the right. To resize the button, you can either edit its Height and Width properties in the Properties window, or, you can simply "grab" it with the mouse, and resize it. To do this, point the mouse at one of the "sizing handles" (the white squares on the sides and corners of the control). You'll see the mouse pointer change to a diagonal dual-headed arrow, which indicates that when you resize from here, you'll be changing both width and height. (If you move the mouse over the top or side border, the mouse pointer will be either vertical or horizontal, indicating the ability to change either height or width; moving anywhere else over the control results in a pointer with four arrows, which allows you to move the control; however, since positioning a control's XY coordinates has no effect in a standard HTML page, it should be disregarded.) To do the actual resizing, hold down the left mouse button, then, drag the mouse toward the center of

the control. You'll see a rectangle composed of a dotted-line follow the mouse, indicating the new size, as shown in Figure 4.8. FIG. 4.8 Resizing a control. When you release the button, the control will resize to the new size, as shown in Figure 4.9. After you've resized the control, click the Close button in the upper-right-hand corner of the "Edit ActiveX Control" window to save the changed properties back to your HTML page. FIG. 4.9 Control after resizing.

Adding Event Code


Before you can do anything with the button, you'll need to add some event code in a script to intercept mouse clicks. The easiest way to do this is to use the Script Wizard that's built into the ActiveX Control Pad. To bring up the Script Wizard, point the mouse anywhere over the gray area to the left of the editing window (other than over a control button) and click the right button. This will display the context menu, as shown in Figure 4.10. Select "Script Wizard", and click.

As this book goes to press, Microsoft is suggesting placing scripts in the <HEAD> section in some of their documentation, and at the end of the <BODY> section in other writings. The execution of scripts is unaffected by placement, and the pre-release version of the Script Wizard currently available for testing places scripts in the <BODY> section. This may change in future releases of the Control Pad.

FIG. 4.10 Selecting the script wizard. The Script Wizard, shown in Figure 4.11, provides a convenient platform for creating event code and procedures, and, an easy way to insert property settings and invoke methods for controls and objects. FIG. 4.11

The script wizard. The Script Wizard consists of three main areas: two tree lists, and one code window. The code window has two modesit can be used in "List View," or "Code View". (Figure 4.11 shows List View.) In List View, it displays a list of actions taken when events occur. These actions are generated automatically according to selections you make. In Code View, the Script Wizard creates event code headers, and property and method code skeletons for you, and lets you write whatever other code you want.

List View
The outline list on the left is captioned "Select an Event. It contains a list of objects on the page, and, when expanded, shows the events that each object exposes. Click the plus ("+") sign next to "CommandButton1" to expand its list of events, and click "Click". You'll then see "On CommandButton1 Click Perform the following Actions:" in the bottom pane, as shown in Figure 4.12, indicating that the Script Wizard has created an Event Procedure for the button's Click event. FIG. 4.12 Creating an event procedure. Now, it's necessary to place some code into the routine. (When the user clicks the button, any code residing in its Click procedure (or "routine") will be automatically executed.) The Script Wizard makes this easy. In the outline list on the right("Insert Actions:"), click the plus sign next to "Window", to expand the properties belonging to the Window object. You'll then see a number of entries (shown in Figure 4.13), several of which also show plus signsthe Window object consists of a hierarchy nested several layers deep. FIG. 4.13 The window Object Hierarchy. Find the entry for "location", and click its plus sign to expand it, then click href, as in Figure 4.14. FIG. 4.14 Expanded view of window.location. At this point, it's time to tell the Script Wizard what to do with the href property. So, double-click "href", and a dialog captioned "Change Window.location href" appears. It will contain a textbox, with a caption saying, "Please enter a string constant value". Type http://www.microsoft.com, as shown in Figure 4.15, then click the OK button. FIG. 4.15

"Change window.location href" dialog box. After you click OK, the bottom panel will contain an entry saying Go To Page "http://www.microsoft. com" as shown in Figure 4.16. Click the Script Wizard's OK button to return to the HTML editing window, and the script it's just created will be inserted into the <BODY> section, shown in Figure 4.17. You're now ready to save the updated file, and run it. (If you've still got the previous version of Page1.htm loaded in Internet Explorer, just click the "Refresh" button on its toolbar to have it load the new version.) FIG. 4.16 Event entry created by script wizard. FIG. 4.17 Script inserted into HTML. When you run the example, it will appear exactly as it did in Figure 4.7, before you added the script. To demonstrate the fact that it's changed, click the button. This time, instead of nothing happening, as it did before, you'll be transferred to the Microsoft home page. (To return to the page you just created, click the "Back" button on Internet Explorer's toolbar.)

Code View
In the gray area to the left of the editing window in Figure 4.17, you can see a button next to the script that the Script Wizard inserted. Just as controls have buttons to bring up the control editing windows, scripts have buttons to bring up the Script Wizard. You use the Script wizard for editing existing scripts, as well as for creating new ones. Click the button, and you'll be back in the Script Wizard. Now, click the "Code View" option button, and you'll see that the bottom panel now shows the actual code created by the Wizard, shown in Figure 4.18. FIG. 4.18 Event code in script wizard. The event code consists of two lines: Sub CommandButton1_Click() Window.location.href = "http://www.microsoft.com"

The first line is the procedure declaration. It's in a section by itself, and, you can't edit it. (Actually, you can edit it, but to do so you need to right-click over it, and select the "Edit Procedure Prototype" option.) The second line is the actual code, and, you can edit its section. Change it by adding one line above it, and one below it, and, indent the original line, as shown below, and in Figure 4.19, then click the OK button to return to the HTML editor. If MsgBox("Really Go West?", 4) = 6 Then Window.location.href = "http://www.microsoft.com" End If FIG. 4.19 Script code after editing. When you're back in the HTML editor, save the file, and reload it into Internet Explorer, then run it again by clicking the "Go West!" button. You'll see a message box asking "Really Go West?", which has two buttons: "Yes," and "No," and is shown in Figure 4.20. FIG. 4.20 Message box in Internet Explorer. If you click the "No" button, nothing will happen; if you click the "Yes" button, you'll be taken to the Microsoft web site.

Although this example used the href property to change to a new URL, it's such a common operation that the Script Wizard offers an easy way to automate it. Just right-click over the lower panel of the Wizard, and you'll see a context menu which offers you a shortcut to insert "go to page" code. It makes it really easy to use controls for creating links to other pages, without writing a single line of code. You'll find this especially useful when you use the ActiveX Control Pad in HTML Layout Page mode, which is covered in Chapter 5, "Creating an HTML Layout Page".

From Here...
In this chapter, you learned how to use the ActiveX Control Pad to create standard HTML pages. You

discovered how to insert and edit ActiveX controls, and work with scripts.
q

q q

See Chapter 6, "Creating an HTML Layout Page," to learn how to use the ActiveX Control Pad to create powerful VB-style pages. See Chapter 11, "Designing VBScript Applications," to see how to use the language elements to create script-enabled pages. See Chapter 15, "VBScript Data Types and Variables," for information on variant sub-type issues. See Chapter 16, "VBScript Operators," for coverage of Arithmetic, String, Comparison, and Logical operators. See Chapter 19, "VBScript Control of Flow and Error Handling," which delves into the looping and testing structures, and the Error Object. See Chapter 21, "VBScript Operators," for more information on declarations and procedures. See Que's Special Edition, Using Visual Basic 4, and Visual Basic 4 Expert Solutions, for extensive information on the Visual Basic language. Refer to the "Microsoft Visual Basic Scripting Edition Language Reference," for exhaustive syntax descriptions and requirements of all statements, functions, and methods.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 5 - Internet Explorer


by Ron Schwarz

This short chapter provides you with a brief synopsis of what browsers are, what they do, and what you can do using the functionality they provide. Chances are you've been using a browser for a while, and, there's a good chance it's a version of Netscape. Don't be surprised if you find yourself quickly moving to Internet Explorer. Microsoft is in the process of standing the browser world on its ear, and you're right in the middle of it. Whatever browser you've been using, it appears very likely that you'll be surfing the Net with Internet Explorer before too long.
q q q q q q q q

Browsers and the World Wide Web A quick overview of what the WWW is, and the job browsers perform. Three generations of browsers Internet Explorer 3.0, the newest version, has a long and colorful history. Current art What browsers can do today. The future Where browser technology is headed.

First Generation Browsers


The first widely available graphical browser for the WWW was NCSA Mosaic (see fig. 5.1). Lynx, a character-based browser (still popular with UNIX users) allowed connection to Web sites, reading text, and downloading files. Although the early browsers were crude by today's standards, they were revolutionarythey enabled fast, easy, hypertext access to information on computers located all over the world. FIG. 5.1 A view of Mosaic, a first generation browser. At this time (the early '90s), the Internet was still somewhat unknown outside of academia and

government, and Web traffic was a small percentage of the overall volume of data moving over the Net. Most information traveling over the Internet consisted of e-mail, remote Telnet sessions, and FTP file transfers. The available bandwidth was sufficient for the traffic.

Second Generation Browsers


After the success of Mosaic, Netscape Navigator was released by Netscape Communications Corporation (see fig. 5.2). It offered better graphics, better formatting, and more features. Eventually, it provided the ability to use plug-ins and Java applets (programs that run within the browser), which provided a means for enhancing and expanding the basic operation of Netscape Navigator. FIG. 5.2 Netscape Navigator, a second generation browser.

Third Generation Browsers


The end of the second generation of browser technology is marked by a user base consisting of incredible numbers of people in all walks of life, as well as a somewhat discouraging reality. For all its potential, the Internet (widely, and incorrectly considered synonymous with the WWW) has become the moral equivalent of television.

The More Things Change...


The Internet has become television for the nineties. The remote control has been replaced by the mouse; rather than waving their clickers at the tube, users slide their mouses over their desks, in clicko-ramic ecstasy, viewing, viewing, and viewing. Instead of changing channels, they surf the Web. Instead of poring through their local television listings, they pull down their Favorites menus. The interactivity of the Web has developed in a way that is heavily weighted in one direction. Web site construction has been a labor-intensive endeavor, requiring a significant measure of skill, and a non-trivial level of physical infrastructure in terms of server hardware, server OS, high-speed Internet connection, and ongoing maintenance. The consumer end of the equation, however, has become embarrassingly simple. Point-and-Shoot interfaces have never been more ubiquitous (with the possible exception of the age of Samuel Colt), and The Web is an inescapable facet of contemporary life. Apart from the difficulties that have accompanied the creation of Web content, the fact remains that browsers, for all their utility, have essentially been little more than hypertext formatting and display engines. Actually, traditional WWW content has been little-different in concept from the common WinHelp files that have been used all along by every Windows user. The difference is that in addition to being able to link to "pages" within the same "document," they can also link to content on other computers. Other than that, they have been near-identicaltext formatted to fit any size window, highlighted hot-links, hotspotted graphics, and a Back button.

Beyond "Virtual Television"


Things are changing, though, as we enter the third generation of browser technology. Java, JavaScript, and Plug-ins created the possibility for interactivity beyond mere "clicking." However, it's one thing to have potentialit's another thing entirely to actualize it. Java is based on C++, and while a bit less complex, is still not for the faint of heart. Plug-ins are a proprietary solution that require special programming techniques which are not portable to environments other than supporting browsers. Just as Windows did not really take off so long as all programming had to be done using the complex Windows SDK (Software Development Kit) and the C language, truly widespread interactive applications over the Web have not proliferated. At the same time as all this growth has occurred on the Internet, Microsoft has been quietly creating the tools to use the Internet (and Intranets) to completely revolutionize the way people use computers.

Opportunities for the Taking


The Microsoft Internet Explorer 3.0 represents state-of-the-art browser technology (see fig. 5.3). In addition to supporting Java and JavaScript (as this book goes to press, Plug-in compatibility is expected, but not yet implemented in the available beta of IE 3.0), Internet Explorer 3.0 provides ActiveX and VBScript compatibility. ActiveX technology is perhaps the most widely-accepted standard for component-level programming. It's used as the basis for Visual Basic 4.0, the most popular programming language in history, and it's also used by numerous other programming languages and major applications. By making it the foundation of Internet Explorer, Microsoft has cleared the path for a genuinely monumental change in what the Web is, who uses it, and how it's used. This is a good time to be a Visual Basic programmer. FIG. 5.3 Internet Explorer 3.0.

Internet Explorer vs. Netscape Navigator It's really difficult to predict the future of Netscape Navigator. After all, at this time, it is the most popular browser. However, it seems to be headed in a direction different

from that chosen by the designers of Internet Explorer. It's entirely likely that Internet Explorer will become the predominant Web browser; not only is it bundled with Windows, and available for free download for other OSs, but future versions will be fully integrated with Windows (see "Browser Extensibility" in this chapter) and be part of the OS. While Netscape seems less than enthralled with the idea of building in ActiveX compliance, at least one third-party vendor has announced a Plug-in designed to support ActiveX components within Netscape. Whether this type of solution will be viable for the majority of Netscape users (particularly in light of the momentum Internet Explorer is generating), remains to be seen. One thing does seem clear: you won't go wrong supporting Internet Explorer. There is more than a bit of irony in all this: Netscape Navigator swept the market out from under Mosaic, by offering a better, easier to use, more capable browser. Now, it appears that the mantle may be passing back, after a fashion. Internet Explorer is based in large part on Mosaic, licensed by Microsoft. "What goes around" may be about to "come around."

Browser Extensibility
Internet Explorer 3.0 is the most highly-extensible browser available. It supports ActiveX controls and documents, HTML Layout Pages, Java applets, has built-in VBScript and JavaScript interpreters, and is expected to support Netscape Plug-ins when released. Elements that add to the power and versatility of Internet Explorer fall into a group of overlapping categories: Objects, Scripts, and Containers.

Objects
The broad category of "Objects" currently includes such diverse items as ActiveX controls and documents, other OLE components, Plug-ins, and, of course, the Internet Explorer object hierarchy. According to information Microsoft has publicly disclosed, the next version of Visual Basic will provide the means to create ActiveX controls. This means that in the not-too-distant future, any competent VB programmer will be able to create virtually any type of Web automation required. Just as the first release of Visual Basic made it possible for thousands of Windows applications to be created by people other than hard-core C programmers, it will soon be possible for these same people to create stunning Internet applications.

Scripts
Scripting languages such as VBScript provide a "glue" to connect the objects. If you're familiar with Visual Basic, you know that a VB application consists of controls placed on forms, with VB code tying it all together. Properties, events, and methods interact with objects to create full-featured applications. VBScript performs the same function in the context of Web pages. ActiveX objects are enabled by virtue of scripts that hook into their exposed properties, events, and methods.

Containers
One of the drawbacks inherent in the nature of HTML browsers is the fact that HTML was designed to be a simple hypertext formatting language. Text flows in from the upper-left corner of the page, and is "fitted" to the current dimensions of the browser. If you resize the browser, the text reformats. This is fine, as far as it goes. And, for content that is primarily comprised of text, with a few images tossed in for good measure, it is perfectly sufficient. Unfortunately, that's not what happened. The Web was pressed into service for a wide variety of presentation purposes, and the ability to create and display visually attractive pages became very necessary, and very difficult. Various "hacks" were mixed into the HTML language. Things like tables allow a bit more control over positioning, but even then, items within table cells are still cursed by their Upper-Left-LowerRight flow-of-text HTML heritage. As the language grew, it became more convoluted, difficult to master, and proprietary. The root of the problem lied in the inability of HTML to place an element at a particular XY coordinate. The very notion of fixed-placement of objects runs counter to the "stream" method HTML uses to fill a page with text. HTML Layout Pages address the problem head-on, and provide an elegant solution. By placing an HTML Layout Page on your Web page, you give yourself the ability to use a tool like the ActiveX Control Pad to visually, interactively place and size controls on a window that looks remarkably similar to a typical Visual Basic form. Because the Layout Page provides a "non-HTMLish" context, you can create everything from beautifully formatted Web pages with rich content, to sophisticated programs that depend on a fixed-positioning of their controls. It should not surprise to anyone if HTML Layout Pages become the de facto standard, displacing traditional HTML for all but the most trivial of Web pages, just as Windows has edged DOS off the desktops of millions of computer users.

Just Over the Horizon


As exciting as things are now, it's important to remember that we're in the midst of a transitional

phase. So, where are things headed? You've probably heard the code name "Nashville" mentioned recently. You may have heard that it's the next version of Windows. Maybe you've heard it's the next version of Internet Explorer. Or, perhaps you've heard that it's a major add-on to Windows 95. Like the proverbial blind men analyzing an elephant, all of the above is true. Nashville (currently being called Internet Explorer 4.0) combines Windows 95 and Internet Explorer into an integrated environment providing seamless continuity between documents on your local computer, other computers on your local Intranet, and other computers on the Internet. Although Microsoft has not released too many details of what the Nashville upgrade will possess, they've dropped enough tantalizing tidbits to make any programmer's mouth water.

Desktop as Browser, Browser as Desktop


As the desktop metaphor is merged with browser technology, it will complete the transformation to document-centric computing. Users will work with documents, regardless of where they reside, regardless of which application they belong to. In fact, most major applications will become nearly invisible, as they work behind the scenes to service their documents. As users browse from document to document (or document embedded within document), the appropriate applications will quietly take over in the background. OLE 2.0 provided a great deal of the required capability, but users still needed to run applications to work with documents. Even when double-clicking on a document's icon, the OS still had to present the user with an application to run. Double-click on a Word document, and a few seconds later, you'll be in Word, ready to view, edit, or print, that document. In the near future, everything will be done in a browser window; you'll work with all kinds of documents within that window, and the actual applications will become, in essence, extensions to the operating system. Documents themselves will change too; while documents are currently based on the paper metaphor, and by nature static, ActiveX technology will enable the creation of dynamic documents, containing a mix of content and logic. What's really happening is a blurring of the lines of demarcation between code and content. Code, content, and location are being mixed together into a potent brew. Those who see what's happening now, and where it's headed in the near future, will be in a position to ride the waves with aplomb, and chart their own course.

From Here...
q

See Chapter 3, "Introducing the ActiveX Control Pad," and Chapter 6, "Creating an HTML Layout Page," to understand features of the new HTML Layout Pages. See Chapter 11, "Designing VBScript Applications," to learn how to integrate the new browser capabilities into your Web applications.

q q

See Que's Special Edition Using HTML, Second Edition, for information on HTML. See Que's JavaScript by Example, for information on JavaScript.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 6 - Creating an HTML Layout Page


by Ibrahim Malluf

q q q q q q q q

Rules and benefits of 2-D layouts This ncludes excerpts of a White Paper presented by Microsoft, Creating and populating layouts by using the ActiveX Control Pad You will see how to design and place your layout. Code management You learn to use the Script Wizard to mange your code development. Creating a project called the Navigator This is a project that creates a Layout Control based drop-in-place navigational tool.

In Chapter 3, "Introducing the ActiveX Control Pad," we talked about the mechanics of the ActiveX Control Pad and its features. The Layout control was introduced along with an example Layout Control project that demonstrated the ActiveX Chart control. Here I present a little more detail Onthe Layout control. The Layout control will be distributed as part of the Internet Explorer 3.0 release version. It is an ActiveX Control that can be distributed to any browser that supports ActiveX controls. In the case of Netscape, ActiveX is not directly supported, but there is at least one add-on available that gives Netscape ActiveX compatibility, and thus Layout Control capability.The ActiveX Layout control gives you full two-dimensional layout capability for your Web pages. Within this control's area, you can place items wherever you desire using pixel granularity. It should be mentioned here that the Layout control is envisioned by Microsoft as an interim application of a preliminary specification approved by the World Wide Web Consortium(W3C). This new specification will include HTML extensions that will radically extend layout capabilities within your documents. For now though, the Layout Control is the tool for providing 2D layout in HTML pages. As currently implemented, the Layout Control requires that you place your 2D layout information in a separate file with an .ALX extension. This file is a text file that contains the layout information formatted in the W3C's preliminary syntax. In this chapter you learn about the benefits of true 2-dimensional layout and design capabilities provided by the Layout control. You also see how to use the Script Wizard to manage VBScript development within this Layout Control. Finally, there is an application project that provides an example of using the Layout control and how to work around some of its limitaions.

Preliminary 2-D Layout Rules and Benefits


q

q q

2-D regions must be defined in a separate file. This file must be given an .ALX extension and is defined as part of the HTML Layout control object tag within the HTML stream. (Please note that after the W3C 2D-layout specification is finalized, Microsoft will support 2-D-style layout definitions directly within the HTML document, rather than in a separate file.) Objects defined within the 2-D region must be ActiveX-compliant objects. The 2-D region must be enclosed within <DIV> tags as follows: <DIV STYLE="LAYOUT: FIXED; HEIGHT value WIDTH value">...</DIV>

According to Microsoft, they are committed to supporting the final specification natively within the Microsoft Internet Explorer after the W3C standard is formalized. Microsoft also says that they will ensure that the HTML Layout Control format is compatible with future 2-D layout support, which will be incorporated directly into future releases of the Microsoft Internet Explorer. The advantages of this new specification include the following:
q

q q

Exact 2-D placement: Controls are placed exactly where the author intended them to be placed within the 2-D region. Overlapping regions: The author can also specify the exact z-order of each control on the page. Transparency: Graphics, labels, and other controls that support transparency can be placed over each other, giving an attractive layered look. Scripting: The HTML Layout control also fully supports scripting, including both Visual Basic Scripting Edition (VBScript) and JavaScript.

Creating and Populating the Layout


To use a Layout Control in your Web page document, you need to declare it as you would any other ActiveX control. Listing 6.1 shows a sample declaration of an ActiveX Layout control in a Web page document.

Listing 6.1 CHAPT6_01.HTMSample Declaration of an ActiveX Layout Control in a Web Page <HTML> <HEAD> <TITLE>Navigator Demo</TITLE> </HEAD> <BODY> <OBJECT CLASSID="CLSID:812AE312-8B8E-11CF-93C8-00AA00C08FDF" ID="Navigator" STYLE="LEFT:0;TOP:0"> <PARAM NAME="ALXPATH" REF VALUE="Navigator.alx">

</OBJECT> </BODY> </HTML> Within the ALX file itself you will also find plain text describing the different items to be contained within the Layout control. All of the ActiveX controls that you place within a Layout control have their object declarations placed with a set of <DIV>...</DIV> tags. Listing 6.2 illustrates the code required to place a TabStrip control within an ActiveX Layout control.

Listing 6.2 NAVIGATOR.ALXThe 2-D Layout Code within an ALX File Specifying a TabStrip Control's Placement <DIV STYLE="LAYOUT:FIXED;WIDTH:134pt;HEIGHT:144pt;"> <OBJECT ID="tabNavigator" CLASSID="CLSID:EAE50EB0-4A62-11CE-BED6-00AA00611080" STYLE="TOP:0pt;LEFT:0pt;WIDTH:124pt;HEIGHT:132pt;TABINDEX:0; ZINDEX:0;"> <PARAM NAME="ListIndex" VALUE="1"> <PARAM NAME="Size" VALUE="4374;4657"> <PARAM NAME="Items" VALUE="Tab1;Tab2;"> <PARAM NAME="TabOrientation" VALUE="2"> <PARAM NAME="TipStrings" VALUE=";;"> <PARAM NAME="Names" VALUE="Tab1;Tab2;"> <PARAM NAME="NewVersion" VALUE="-1"> <PARAM NAME="TabsAllocated" VALUE="2"> <PARAM NAME="Tags" VALUE=";;"> <PARAM NAME="TabData" VALUE="2"> <PARAM NAME="Accelerator" VALUE=";;"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> <PARAM NAME="TabState" VALUE="3;3"> </OBJECT> </DIV>

Parts of a Layout Control Page


The <DIV> tag syntax is : <DIV [ID=name] STYLE = "layout-style-attributes">

object-blocks </DIV> The ID part of the tag is an optional attribute that specifies the name given to that particular Layout control and is used by scripting to identify it. The style tag specifies the style attributes for a given Layout Control and are defined in Table 6.1. Table 6.1 Style Attributes for <DIV> Tag Attribute LAYOUT HEIGHT WIDTH Description Must be defined as FIXED for a 2-D region Specifies the height of the layout region in pixels Specifies the width of the layout region in pixels

BACKGROUND Specifies the background color of the layout region in HEX digits You can include any ActiveX control within your ALX file. This includes but is not limited to controls that implement the ActiveX Control '96 specification for windowless, transparent controls. One thing I should note however is that some ActiveX controls will require a developer's license for you to include and distribute them through your Web documents. The beta version of Internet Explorer that I am working with right now does not have the licensing mechanism in place and will not show any controls that require a license. This should be corrected by the time you are reading this book.

One thing I should note, however, is that some ActiveX controls, you will have to have require a developer's license for you to include and distribute them through your Web documents. The beta version of Internet Explorer that I am working with right now does not have the licensing mechanism in place and does not indicate which controls require a license. This should be corrected by the time you are reading this book.

How to Start a New Project Fortunately, you do not have to hand edit these ALX files. You can produce them through the ActiveX Control Pad described in Chapter 3, "Introducing the ActiveX Control Pad." To create a new Layout control, you need merely select the New Layout Control from the Files menu of the ActiveX control menu as shown in Figure 6.1. This brings up a new ActiveX Layout control that is ready for your editing.

FIG. 6.1 Select a New HTML Layout control from the menu of the ActiveX Control Pad. Let us create a navigator tool that can act as a drop-in-place navigational object that is fully modifiable based on a given page context. The idea being presented here uses a Layout control that contains a TabStrip control and an ieLabel control. The number of displayed tabs will differ depending upon the modifications made by external sources such as the parent Web page, or even a Web page in another frame. First we'll begin by create the new Layout Control, adding a tab control and ieLabel control, and arrange them as shown in Figure 6.2. The TabStrip is named tabNavigator, and the label is simply named ieLabel. The TabStrip's TabOrientation property is set to left, and the ielabel's angle property is set to 90 degrees. Finally, add a ieTimer control that will drive some animation effects to be added later. Save the control with the name of Navigator.alx. FIG. 6.2 Begin the Navigator Demo project within the ActiveX Control Pad. So altogether there are three controls on the Layout Pad. The ieLabel control in this beta version of the ActiveX Control Pad would not permit changing the FontName property from the Properties Edit Window. This is a bug that might or might not get fixed before you get an opportunity to read this book. The workaround for this and many similar problems is to directly edit the properties using the 'View Source Code' selection from the right button click's pop-up menu. This produces a NotePadbased edit window that enables you to do direct editing. Listing 6.3 shows the HTML code as presented by the View Source Code menu selection. Note that I changed the ieLabel's FontName to Brush Script MT.

Listing 6.3 NAVIGATOR.ALXThe Navigator's <DIV> Code Section in the ALX File with the Modified FontName Property of ieLabel <DIV STYLE="LAYOUT:FIXED;WIDTH:125pt;HEIGHT:250pt;"> <OBJECT ID="tabNavigator" CLASSID="CLSID:EAE50EB0-4A62-11CE-BED6-00AA00611080" STYLE="TOP:0pt;LEFT:0pt;WIDTH:124pt; HEIGHT:248pt;TABINDEX:0;ZINDEX:0;"> <PARAM NAME="ListIndex" VALUE="0"> <PARAM NAME="Size" VALUE="4374;8749"> <PARAM NAME="Items" VALUE="Tab1;Tab2;"> <PARAM NAME="TabOrientation" VALUE="2">

<PARAM NAME="TabFixedWidth" VALUE="2646"> <PARAM NAME="TipStrings" VALUE=";;"> <PARAM NAME="Names" VALUE="Tab1;Tab2;"> <PARAM NAME="NewVersion" VALUE="-1"> <PARAM NAME="TabsAllocated" VALUE="2"> <PARAM NAME="Tags" VALUE=";;"> <PARAM NAME="TabData" VALUE="2"> <PARAM NAME="Accelerator" VALUE=";;"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> <PARAM NAME="TabState" VALUE="3;3"> </OBJECT> <OBJECT ID="IeBanner" CLASSID="CLSID:99B42120-6EC7-11CF-A6C7-00AA00A47DD2" STYLE="TOP:8pt;LEFT:83pt;WIDTH:33pt; HEIGHT:231pt;TABINDEX:1;ZINDEX:1;"> <PARAM NAME="_ExtentX" VALUE="1164"> <PARAM NAME="_ExtentY" VALUE="8149"> <PARAM NAME="Caption" VALUE="The Navigator Demo"> <PARAM NAME="Angle" VALUE="90"> <PARAM NAME="Alignment" VALUE="4"> <PARAM NAME="Mode" VALUE="1"> <PARAM NAME="FillStyle" VALUE="0"> <PARAM NAME="FillStyle" VALUE="0"> <PARAM NAME="ForeColor" VALUE="#612238"> <PARAM NAME="BackColor" VALUE="#C0C0C0"> <PARAM NAME="FontName" VALUE="Brush Script MT"> <PARAM NAME="FontSize" VALUE="32"> <PARAM NAME="FontItalic" VALUE="0"> <PARAM NAME="FontBold" VALUE="0"> <PARAM NAME="FontUnderline" VALUE="0"> <PARAM NAME="FontStrikeout" VALUE="0"> <PARAM NAME="TopPoints" VALUE="0"> <PARAM NAME="BotPoints" VALUE="0"> </OBJECT> <OBJECT ID="IeTimer1" CLASSID="CLSID:59CCB4A0-727D-11CF-AC36-00AA00A47DD2" STYLE="TOP:173pt;LEFT:17pt;WIDTH:25pt; HEIGHT:25pt;TABINDEX:2;ZINDEX:2;"> <PARAM NAME="_ExtentX" VALUE="873"> <PARAM NAME="_ExtentY" VALUE="873"> </OBJECT></DIV> So if you are working with an ActiveX control that is giving you trouble modifying a property value, you can try using the text editor to manually modify that value. One thing I should warn you about,

some properties that are not recognized, or other text like comments that are manually typed in by you between the <DIV> and </DIV> tags will be removed by the ActiveX Control Pad the next time it reads in the ALX file.

Code Management
The Script Wizard gives you very good control over the editing environment within a Layout control. All of the event code for your controls can be written through the Script Wizard using the Select Event and Insert Actions tree views. You can even add non-event procedures and Global variables through the Script Wizard as well. Figure 6.3 shows the pop-up menu that appears when right-clicking the Procedures node in the Insert Actions tree view. When selecting a New Procedure from this menu, the Script Wizard opens a Code window to that procedure with the default name of Sub Procedure1In this situation a Function is desired instead of a sub procedure. Left-click the mouse button into the area where the procedure name is and edit the text there to say "Function NewColor." This function will be used to return a number representing a randomly generated color. It will be called by the ieTimer_timer event to provide a little bit of animation. FIG. 6.3 Add code to the Change event of the tabNavigator tabstrip. To add functionality to a control's event procedure, just select the correct event from a control node in the Select Event window of the Script Wizard. Figure 6.4 shows the tabNavigator_Change event selected and the appropriate code being added to the event. FIG. 6.4 Edit the code in a Procedure through the Script Wizard. Let's get down to the code required to build this drop-in-place navigator tool. Listing 6.4 includes three event procedures and one utility procedure. The utility procedure is a function that returns a randomly generated number. The ieTimer_Timer event calls a function that randomly generates a new number for the ieBanner label's text. The tabNavigator_Change event calls a ChangedTab procedure in the parent document.

Listing 6.4 NAVIGATOR.ALXThe VBScript Code within the HTML Layout Control for the Events and Methods of the Navigator.ALX Demo

<SCRIPT LANGUAGE="VBScript"> <!-'=================================== ' Global Variables '=================================== dim blnLoaded '=================================== ' Event Procedures '=================================== Sub Navigator_OnLoad() rem:'to prevent the double load rem:'bug use a global flag that rem:'indicates a prior pass through rem:'the OnLoad event. If blnLoaded Then Exit Sub Else 'first time through blnLoaded = true 'make sure the MyTabs value is numeric If IsNumeric(PARENT.FRAMES(1).MYTABS.Value) Then For lngTabCount = 1 To PARENT.FRAMES(1).MYTABS.Value call tabNavigator.Tabs.Add() Next Else MsgBox "ERROR: MyTabs hidden value not found or" _ & vbCRLF & " contains non-numeric value on parent" End If rem:'call the function that provides the names and locations rem:'of the navigator's tabs. rem:'if the procedure is missing then rem:'let the user know On Error resume next If Err then MsgBox "The NameTabs Procedure was not found on Parent" End If End If end sub Sub IeTimer1_Timer() if Navigator.tabNavigator.Tabs(0).Caption = "LoadTabs" then Parent.Frames(1).NameTabs End if rem:'get a randomly generated color for the text ieBanner.ForeColor = NewNumber(&HFFFFFF) end sub Sub tabNavigator_Change()

rem:'call the action specified in the parent's ChangedTab procedure On Error Resume Next CALL Parent.FRAMES(1).ChangedTab(tabNavigator.SelectedItem. Index) if err then msgBox Err.Description end sub '=========================================== ' Utility Procedures '=========================================== Function NewNumber(lngLimit) Dim lngNumber rem:'make sure that the argument rem:'is a numeric value If Not IsNumeric(lngLimit) Then lngNumber = &HFFFF Else lngNumber = lngLimit End If NewNumber = int(rnd * lngNumber) + 1 End Function --> </SCRIPT> The Navigator_OnLoad event contains special code to deal with some vagaries of the relationship between a parent document and the ALX file. There are some very tricky timing issues involved with the Layout Control and the parent document's VBScript. In the case of this Navigator project I wanted to be able to have the parent document determine how many tabs would be needed, what those tabs' titles would be, and finally what would happen when those tabs where selected. The problem here had to do with the way the VBScript would be parsed by Explorer. In order to have the parent document's VBScript recognize the Navigator Layout control I had to use the OnLoad ="InitALX" event in the VBScript of the parent document. This will cause the Navigator to get loaded before the VBScript is parsed thus avoiding parsing errors when the parser came upon references to the navigator. The caveat here was that none of the Parent Document's VBScript code could be run outside of a procedure or a parser error would occur anyway. So I had to have a way to invoke the parent document's VBScript code that would populate the tabstrip with data. The Navigator's OnLoad event did the trick. Since the ALX code apparently gets parsed while loading, and this particular event wouldn't occur until the Navigator was loaded all the timing issues of the parser were resolved. The OnLoad event of the Navigator called back to the parent document's VBSCript procedure that loaded the tabstrip with the data. This problem is purely an initialization problem. Once the parent document has completed loading, the Navigator's data can be manipulated from other frames as needed.

Saving and Running


The Navigator Demo created here has a set of requirements in order to run. They are:
q q q

A Hidden Control named MyTabs that specifies the initial number of tabs to display A Subroutine named 'NameTabs()' that provides the Tab names and related URLS A Subroutine named 'ChangedTab(MyTab)' that takes a numeric argument and acts upon the tab number provided to it by the Navigator The Navigator Demo must reside in Frame 1 of a three frame project.

You can modify the Navigator to have different requirements depending upon your needs but as it is presented here these are the things it needs to work To build and test your Layout Controls you need to have one or more Web page documents to create the environment needed for your layout control project. In my case here I needed three documents:
q q q

Chapt6_00.htm: The document that creates the three frames MyBanner.htm: The document that creates a title at the top of the window Chapt6_01.htm: The document that contains the Navigator and related code

The code for Chapt6_00.htm includes the definition of three frames that have no borders and are not sizable. Listing 6.5 shows the code for this page. You won't find any rocket science there.

Listing 6.5 CHAPT6_00.HTMThe Layout HTML for the Required Frames <HTML> <HEAD> <TITLE>MainFrame</TITLE> </HEAD> <BODY> <FRAMESET ROWS="55,*" FRAMEBORDER=NO> <FRAME SRC="MyBanner.htm" NAME="MyBanner" SCROLLING=NO NORESIZE> <FRAMESET COLS="180,*"> <FRAME SRC="Chapt5_01.HTM" NORESIZE SCROLLING=NO NAME="MCSMENU"> <FRAME SRC="Blank.HTM" NAME="MCSMAIN"> </FRAMESET> </FRAMESET>

</BODY> </HTML> The next page is the MyBanner.htm. While not exactly relevant to the topic of this chapter I am including it to show some of the things you can do with VBScript. Listing 6.6 provides the code.

Listing 6.6 MYBANNER.HTMA Fancy Banner to Fill Frame 0 in the Navigator Demo <HTML> <HEAD> <TITLE>New Page</TITLE> </HEAD> <BODY BGCOLOR="navy" TopMargin=0> <SCRIPT LANGUAGE="VBSCRIPT"> Dim strTitle Dim lngCount Dim lngColor Dim lngRate lngColor = &H0000FF Dim strLetter strTitle="VBScript: The HTML Layout Control" lngRate= &H0001FF\hex(len(strTitle)) For lngCount = 1 to len(strTitle) strLetter = mid(strTitle, lngCount, 1) Document.Write "<SPAN STYLE=color:" & hex(lngColor) _ & ";font-size=0.5in>" & strLetter & "</SPAN>" If lngColor > &H20 then lngColor= lngColor - lngRate Else lngColor =&H0000FF End If Next </SCRIPT> </BODY> </HTML> And now we come to the actual page that contains the navigator. The first part of this page contains the page's layout information including the required hidden control mentioned above and the object declaration for the layout control. This is all in Listing 6.7.

Listing 6.7 CHAPT6_01.HTMThe Layout HTML code for the Navigator Page <HTML> <HEAD> <TITLE>Navigator Demo</TITLE> </HEAD> <BODY TOPMARGIN=0 LEFTMARGIN=0> <INPUT TYPE=HIDDEN VALUE="4" ID="MYTABS"> <OBJECT ID="Navigator" CLASSID="CLSID:812AE312-8B8E-11CF-93C8-00AA00C08FDF"> <PARAM NAME="ALXPATH" REF VALUE="Navigator.alx"> </OBJECT> As you can see, the Layout Control is declared like any other ActiveX object. The remaining code is VBScript Code that directly works with the Navigator Layout Control. The first procedure loads the navigator's TabStrip with titles for the tabs and puts a URL into the corresponding tab's ControlTipText property. Listing 6.8 shows that procedure.

Listing 6.8 CHAPT6_01.HTMThe Procedures for Setting Up and Responding to the Navigator Layout Control <SCRIPT LANGUAGE="VBSCRIPT" OnLoad="initALX"> Sub NameTabs Navigator.tabNavigator.Tabs(0).Caption="HOME PAGE" Navigator.tabNavigator.tabs(0).controltiptext _ = "http://www.mcp.com/que" Navigator.tabNavigator.tabs(1).Caption = "Microsoft" Navigator.tabNavigator.tabs(1).controltiptext _ = "http://www.microsoft.com" Navigator.tabNavigator.tabs(2).Caption="Internet Explorer " Navigator.tabNavigator.tabs(2).controltiptext _ = "http://www.microsoft.com/ie" Navigator.tabNavigator.tabs(3).Caption="Avatar" Navigator.tabNavigator.tabs(3).controltiptext _ = "http://www.avatarmag.com/" Navigator.tabNavigator.tabs(4).Caption="MS Int. Dev." Navigator.tabNavigator.tabs(4).controltiptext _ = "http://www.microsoft.com/intdev/"

Navigator.tabNavigator.tabs(5).Caption="Change Menu" Navigator.tabNavigator.tabs(5).controltiptext _ = "NewMenu.htm" ChangedTab 0 End sub Sub ChangedTab( MyTab) Status = "Getting " & Navigator.tabNavigator.tabs(mytab). controltiptext PARENT.FRAMES(2).Navigate Navigator.tabNavigator.tabs(mytab). controltiptext End Sub </SCRIPT> </BODY> </HTML> With all of this in place, you can load the Chapt6_00.htm and start out with the window shown in Figure 6.5. FIG. 6.5 Here's the Navigator Layout control in action. By clicking any of the tabs of the Navigator control you can cause the indicated Web page to be loaded into the main window of the frameset. Customizing this navigator during runtime is accomplished through the modification of the value in the MyTabs hidden value and the values in the NameTabs Sub procedure to match your location titles and URLs.

From Here...
Try experimenting with the Navigator concept such as having pages that are loaded into the main frame dynamically change the Navigator's tabs and locations data.
q

For more information on developing with the Layout Control using the ActiveX control Pad see Chapter 3, "Introducing the ActiveX Control Pad."

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 7 - ActiveX Objects


by Michael Marchuk

If you haven't read Chapter 9, "An Introduction to Distributed Objects", you may want to go back and at least browse through the information contained there. This chapter will assume you have an understanding of the basics behind distributed application development that were covered in Chapter 9. This chapter focuses on explaining the core ActiveX objects which are included with Microsoft's Internet Explorer 3.0. By understanding these components, you will be able to see how ActiveX objects can fit into your own distributed applications. By now you're probably eager to begin learning how specific ActiveX objects will be able to meet the needs of your interactive Web pages or distributed applications. Specifically, this chapter covers:
q q q q

q q q q

Describing the standard ActiveX This chapter outlines and discusses the Active X objects included with Internet Explorer 3.0. Installing and using ActiveX objects ActiveX objects don't install the way other software does. You'll find out how to get ActiveX objects up and running on your system. Finding ActiveX objects Find out where to look for ActiveX objects to enhance your distributed applications. An overview of ActiveX object development ActiveX object development is not for the faint of heart, but you will find out the general method of how an ActiveX object is created.

Understanding ActiveX Objects


ActiveX objects will become much more real to you after you have read this section. Until now, the discussion of ActiveX objects has been conceptual. Now, you can be exposed to some of the real aspects of installing, using, and programming with ActiveX objects. As you read through the

discussions of the various objects, let your mind wander to the Web pages that you have developed and to the applications which you've been waiting to move on to the Internet. These controls, and the many others which are currently available, will enable your plans for an interactive Internet application to become reality with VBScript.

Installing ActiveX Objects


Chapter 9 mentioned the concept of installing objects using a trust arrangement with a Certificate Authority (CA). Since the ActiveX controls are signed with a digital fingerprint that is verified by a CA, the users which download the objects will feel more confident about the distributed applications they are running. Additionally, you will feel better about the objects that you incorporate into your distributed applications, knowing that they are sealed with a tamper-evident digital signature. You learn how to incorporate ActiveX objects into your Web pages later on in Chapter 11, "Designing VBScript Applications", so for now, assume that you have successfully implemented the object within your HTML document. Since this is a distributed environment, the user who downloads your Web page may not already have the ActiveX component that you have used. In this case, the browser will have to retrieve and install the object before your application runs. Figure 7.1 shows a page which contains an object which is not available locally and must be downloaded. Note the status bar on the bottom of the Internet Explorer window which indicates that the objects are being installed locally. FIG. 7.1 ActiveX objects must be available locally to be used by a distributed application or interactive Web page. After an ActiveX object has been downloaded from an archive, the object must be installed on the user's system. Recall that the digital signature which accompanies the object must be checked with the Certificate Authority which issued the signature. After the signature has been authenticated, the user is presented with a verification dialog like the one shown in Figure 7.2. FIG. 7.2 ActiveX object installation requires the user to accept the validated digital signature from the Certificate Authority that issued it. The user is allowed two options on the dialog box. The first option allows the user to place full trust in the software developer who wrote the object so that when another object by the same vendor is required, the browser will automatically trust the authenticated digital signature and install the software. The second option indicates that any object which is signed by this particular Certificate Authority will be trusted, no matter who the vendor is.

You will have to decide how much trust to place on the various vendors and Certificate Authorities before you answer these questions. It may be wise to leave the automatic acceptance selections unchecked until you feel more comfortable about the vendor or the Certificate Authority.

After an object has been successfully installed on the user's system, any future references to that object will not require the system to reload the object from an archive. If a future Web page is encountered which requires a newer version of the object, the browser will have to download the new object. Now that you've been exposed to the installation of ActiveX objects, lets see what types of objects are available.

Using ActiveX Objects


The ActiveX framework allows an HTML page to contain an OBJECT identifier tag that specifies the various parameters necessary to use a particular object. For example, Figure 7.3 shows a code window which contains the various pieces required to implement an animated button control. FIG. 7.3 ActiveX objects can be added to an HTML page using simple code that describes the operation of the object. As a VBScript developer, you can add any number of ActiveX components to your HTML page to create the environment you need. The OBJECT tag indicates that the information contained within the brackets pertains to a particular object. The information contained within this OBJECT tag will be provided to you by the ActiveX vendor that supplied the component. Typically, a vendor-supplied component would be installed on your system using a standard setup application under Windows. A component can be supplied on a floppy or downloaded from a vendor's Internet server. Once that component has been installed, you need to make the runtime version of that component (if it is different than the developer's version) available on your Web server for others to download when they use your distributed application. The ActiveX properties are assigned using the PARAM tags. Each PARAM tag has a NAME and a VALUE which identify which property is being set and to what value. For example, if a particular ActiveX control included a property for changing the size of the font on the control, you might include a line like the one in the following example. <PARAM NAME="FontSize" VALUE="12">

Since some ActiveX controls will have more properties than others you may add as many PARAM tags as necessary. Most controls will assume a default value if you do not specify a particular property value using the PARAM tag. While this is not bad, it may produce unwanted results. You might be better off explicitly setting each property value to ensure that your application runs and looks the way you want it to. Now that you've seen how the ActiveX controls are added into your HTML pages, let's take a look at some of the default ActiveX controls which the Internet Explorer 3.0 uses.

Animated Button Object


Windows software has been using animated buttons for years. Animated buttons are button controls which allow a series of images to be repeated on top of a button either continuously or when the button changes states. For example, you may have a Web page which includes a search function for your Web site. The animated button you use could have a rotating magnifying glass which scans over pages flying by when the button is pushed. Animated buttons require a certain flair for creativity and graphical art talent, but then you probably already have some of that in you if you've been designing HTML pages. The animated button control provides five events that activate the various animations associated with you control. These events are:
q q q q q

ButtonEvent_Click ButtonEvent_DblClick ButtonEvent_Focus ButtonEvent_Enter ButtonEvent_Leave

Additionally, you may obtain various properties from the button control. Notice that the properties correspond closely to the events listed above. The properties are:
q q q q q q q q q

URL: Specifies the location of the AVI file to display DefaultFrStart: Specifies the starting frame in the default state DefaultFrEnd: Specifies the ending from in the default state MouseoverFrStart: Specifies the starting frame in the mouseover state MouseoverFrEnd: Specifies the ending from in the mouseover state FocusFrStart: Specifies the starting frame in the focus state FocusFrEnd: Specifies the ending from in the focus state DownFrStart: Specifies the starting frame in the down state DownFrEnd: Specifies the ending from in the down state

The animated button has four states. These states are:


q q

Default: No other events are occurring Down: The button is pressed

q q

Focus: The button control has the focus Mouseover: The mouse cursor is currently over the button control

While a button may actually be in multiple states at once, like when the button has the focus and the mouse cursor moves over the button, only one event will trigger at a time. To handle these types of conditions, there are certain states that take precedence over other states. For example, the Mouseover event will trigger when the button has focus. The Down event will trigger even if the button has focus and the mouse cursor is over the control.

Chart Object
Creating colorful charts is easily accomplished using the chart control object. The chart control supports seven basic types of charts:
q q q q q q q

Area chart Bar chart Column chart Line chart Pie chart Point chart Stocks chart

Each of these chart types supports properties (see Table 7.1) that allow you to control the number of rows and columns, grid lines, color schemes, transparency of the background, the scale of the chart, and whether a legend should be included. Additionally, each of the basic chart types may support variations such as simple, stacked, or full. Figure 7.4 shows an example of a chart created by this object. Fig. 7.4 The chart object can create great-looking charts with little effort.

Gradient Control Object


The gradient control object allows an area to be filled with a color which transitions to another color across the area. For example, the installation screens for most Windows applications use a blue to black gradient as a backdrop. The gradient control has few properties (see Table 7.2) that are needed to create this effect. Figure 7.5 shows an example of the gradient object.

Fig. 7.5 The gradient object can be used to create interesting effects. Table 7.2 Gradient Control Object Properties Property Value Description Example

Define the two colors which will be used in the transition. Note that StartColor, EndColor the color is defined by using the standard hexadecimal HTML color codes. Define the coordinates (x,y) within the HTML StartPoint, EndPoint page which will be filled using the specified gradient.

<PARAM NAME="STARTCOLOR" VALUE="#FFFFFF">

<PARAM NAME="STARTPOINT" VALUE="25,25"> <PARAM NAME="ENDPOINT" VALUE="575,75">

Direction

Defines the gradient effect which will be used with the colors specified. The values are: 0 = Horizontal (start at left) 1 = Vertical (start at top) 2 = Towards center 3 = Towards corner <PARAM NAME="DIRECTION" VALUE="1"> 4 = Diagonal down (start at left) 5 = Diagonal up (start at left) 6 = Around the "StartPoint" coordinate 7 = Across the line between "StartPoint" and "EndPoint"

Label Object
The label object allows text to be displayed at an angle on the page using a particular font, color, and style. You may wonder why you would want to use a label rather than just a standard HTML tag such as <FONTSIZE = 7>. The power of the label object comes from two factors: the ability to rotate the

text to any angle, and the ability to use the events triggered by the control. The label object supports several events including:
q q q q q

Click Change MouseDown MouseOver MouseUp

These events will give you the freedom to create interactive text which may spin or change colors as the user moves the mouse over the label's text. Figure 7.6 shows how this object can be used. Fig. 7.6 The label object gives you more freedom when placing text on an HTML page.

New Item Object


There may be times when you want to highlight new items on a particular HTML page. The New Item object handles this by displaying an image until a particular date. After that date, another image may be shown, if desired. Table 7.4 outlines the properties available from the new item object. You most commonly use this object when you add headlines or sections to an HTML to which you would like to draw attention when they've been added. The date parameter also allows you to manage when the added item is no longer considered new. Table 7.4 New Item Object Properties Property Value Date Specifies the date until which the specified graphic will be shown. Specifies the URL to which the image will bedisplayed Example <PARAM NAME="DATE" VALUE=10/31/96> <PARAM NAME="IMAGE" VALUE=http://www.xyz. com/images/new.gif>

Image

Popup Menu Object


You may have a need to use a popup menu within your distributed application. The Popup Menu object allows your HTML page to contain an image or button which causes the menu to appear. The items on the menu are created when the object is loaded. The menu items themselves are activated when the user clicks on the menu item (see fig. 7.7). This action fires the IEPop_Click() subroutine and passes the items list index value. The only property for the popup menu object is listed in Table 7.5. Note that the property may be repeated for multiple items.

FIG. 7.7 The popup menu allows your HTML pages to use new means of gathering data or linking to other pages. Table 7.5 Popup Menu Object Property Property Value Example <PARAM NAME="MENUITEM[1]" VALUE="First Item"> <PARAM NAME="MENUITEM[2]" VALUE="Second Item">

Specifies the item in the Menuitem[] pop-up menu array.

Preloader Object
Your application may make use of some performance enhancements through the preloader object. This object will begin downloading pages in the background while a user is still reading the current page. By doing so, the user will experience a much faster load of the next page since the images and text will already be loaded into the browser's cache directory. It is possible to overuse the preloader object and download everything at once. This is an unnecessary waste of bandwidth and disk storage since the user may not go to the next page. However, you may have a set of Web pages that would benefit from the preloader object. The properties for the preloader object are shown in Table 7.6. Table 7.6 Preloader Object Properties Property Value Description The name of the local file contained in the browser's CacheFile cache. This property is readonly. Data The contents of the file which was read in. This property is read-only. This property switches the control on and off: 0 = Disabled 1 = Enabled This property specifies which file to download when the control is enabled Example

(within VBScript) CachFileName= ieprld.CacheFile

(within VBScript) DataDownloaded= ieprld.Data

Enable

<PARAM NAME="ENABLE" VALUE="1">

URL

<PARAM NAME="URL" VALUE="http://www.xyz. com/pricing.html">

Stock Ticker Object


Your distributed application may call for a constant display of information at the bottom of the screen or within a frame. The stock ticker object can handle this sort of constant update display by downloading an XRT file which handles real-time data. The stock ticker object scrolls the data from right to left as it is loaded. The file which is loaded is refreshed using a periodic interval. The file format of the data follows the XRT format. This format is as follows: XRT file format XRT DataName1<TAB>DataValue1<TAB>DataValue2...<CR><LF> DataName2<TAB>DataValue1<TAB>DataValue2...<CR><LF> The XRT file contains data records which use a tab character to separate the data within the record. The data record may include any number of data values separated by tabs. The record is terminated by a carriage return and a line feed character. For example, an XRT file which contains sports scores might look like this: XRT Cubs/Mets<TAB>10<TAB>3<TAB>Bottom of Ninth<CR><LF> Sox/Expos<TAB>5<TAB>2<TAB>Top of Third<CR><LF> An XRT file can contain as many data elements as necessary, but the display of this data is limited to the stock ticker format. The properties of the stock ticker object are shown in Table 7.7. Table 7.7 Stock Ticker Object Properties Property Value Description Example

These properties specify the color scheme for the background and the <PARAM NAME= "BACKCOLOR" BackColor, ForeColor foreground. The colors VALUE="#FFFFFF"> are indicated using the standard HTML color coding.

DataObjectName

Indicates the data <PARAM NAME= "DATAOBJECTNAME" source. This can be a URL or an OLE object VALUE="http://www.xyz.com/RealTime/ Baseball/ that generates the XRT ALWest.XRT"> data stream. This property is used to toggle the data refreshing. 0 = Data source is inactive. 1 = Data source is active. Specifies how much data is scrolled during each scroll interval.

DataObjectActive

<PARAM NAME= "DATAOBJECTACTIVE" VALUE="1">

ScrollWidth

<PARAM NAME= "SCROLLWIDTH" VALUE="10">

ScrollSpeed

Specifies the interval (in seconds) in which <PARAM NAME="ScrollSpeed" VALUE="1"> the display is scrolled. Specifies the interval (in seconds) between the XRT file reloading. This <PARAM NAME= "RELOADINTERVAL" interval is also used to VALUE="10"> refresh the data stream from an OLE server which is providing the data. Specifies that the data element will be offset from the name element by the indicated <PARAM NAME= "OFFSETVALUES" number of vertical VALUE="-20"> pixels. This gives the appearance or superscript or subscript text.

ReloadInterval

OffsetValues

Timer Object
The timer object will enable your distributed application or HTML page to animate text, change colors of objects, or trigger some other event at a periodic interval. The timer control has only a few properties and one event. The properties for the timer object are shown in Table 7.8.

Table 7.8 Timer Object Properties Property Value Example

The timer control object can be enabled or disabled by setting this Enabled property to the following values: <PARAM NAME="ENABLED" VALUE="TRUE"> True = Timer enabled False = Timer disabled This property specifies the interval (in milliseconds) between event triggers. When set to zero or <PARAM NAME="INTERVAL" VALUE="1000"> a negative number the timer will act as though it was in a disabled state.

Interval

Other Available ActiveX Objects


Many more ActiveX controls are available which can provide the display or processing power which you desire in your distributed application. Currently, Microsoft is maintaining a list of the vendors which are producing ActiveX controls. This list can be found at http://www.microsoft.com/activex/ controls/.

Developing ActiveX Objects


The ActiveX software development kit is currently available only for the Visual C++ environment, however, Microsoft has mentioned that a Visual Basic environment is in the works. This will provide the ability of creating your own ActiveX components to be used on your own or others HTML pages. Developing ActiveX components is beyond the scope of this book, but it should be mentioned that the process and tools for these components are evolving quickly. By the time this book is published, some of the more difficult development tasks surrounding ActiveX object development may be automated by the advancing tools used to create them. But for now, the development of ActiveX objects requires a relatively involved development environment including Microsoft's Visual C++. ON THE WEB http://www.microsoft.com/intdev/sdk/ For more information on developing ActiveX objects see Microsoft's Web site.

From Here...
Now that you've had a taste of the ActiveX controls you can use, you're probably ready to start trying

them out in some sample VBScript enabled pages. Check out the following chapters to see how these controls are used within VBScript:
q

Chapter 11, "Designing VBScript Applications," guides you through the process of properly designing distributed applications using VBScript. Chapter 12, "A Simple VBScript Page," presents a simple example of how to put it all together and produce a functional VBScript page. Chapter 18, "VBScript Event Programming," teaches you about event programming and the how-to's of using VBScript events. Chapter 19, "VBScript Procedures," focuses on defining subroutines and functions for use in your distributed applications.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 8 - Security
by William R. Beem

q q

q q

q q

q q

q q

What types of security are available on the Internet Learn how to select and use different types of security to protect you information assets from unauthorized eyes. How encryption protects documents and files Sending unencrypted files over a network is like sending a postcard through the mail. Anyone can read it. Using encryption is like putting your data in a sealed envelope with a heavy-duty combination lock. Discover how protection works and why you should use it. Why security is essential to electronic commerce Commerce is the exchange of goods and services for money. Nobody wants to send unprotected money across a public network. This section helps you understand why security and commerce go hand in hand. The difference between security specifications and their implementations The Internet abounds with specifications for various topics, and security is no different. As with many other things in life, the difference between theory and practice isn't always what you expect. What security proposals are forthcoming on the Internet If the new security techniques you read about in this chapter teach you anything, it's that more security techniques will appear in the future. The increasing amount of financial traffic and commerce on the Internet will continually demand protection. Learn about it before it happens.

Why Bother with Security?


The concept of Internet security is almost an oxymoron. The purpose behind the Internet is to provide an open communication platform among a cooperative collection of users. The Internet's designers' main purpose was not to protect or conceal information, but rather to publish and share it. No regulating body or government has absolute control over who can access the Internet. Anyone can enter it as a user or provider. Any computer attached to the Internet is almost an open invitation for visitors to peek inside. This model of universal, unrestricted access served Internet users well for many years. The fairly

recent commercialization of the Internet brings forth an entirely new set of users with different objectives, concerns, and strategies. Their entry also brings forth a heightened sense of overcrowding, and with it, a need for privacy. The increasing number of personal computer users brings, unfortunately, increasing occurrences of computer crime. Given this increase of criminal activity, it's only natural that commercial entities on the Internet want to protect their assets. The same is true for individual users who want to practice legitimate, lawful commerce on the Internet. These users see the Internet as a place to gather and exchange information, and also as a new way to purchase products and services. By using current Internet technology, a company can provide information about its specific products to any consumer at any time. Current credit card transaction technology makes it possible for users to send their credit card numbers over the Internet and receive their purchase almost immediately. Attracted by advertising and the ease of buying items with a credit card, consumers are easily lured into making immediate, impulsive purchases. The immediacy of electronic communication thus becomes a strong enticement to buy a product now! Some software publishers are already using this technology to sell and distribute their products and upgrades. Others will surely follow the trend and create a new distribution channel. Though it sounds nice, this online marketplace has the same dangers as the real world. A criminal who knows that you have money will feel compelled to relieve you of its burden. Consider this scenario. The mechanism that sends your money to a vendor is like a robot. It knows that its job is to carry an amount of money from your account to a vendor. It's feasible for a criminal to create a robot of his own that either disguises itself to look like the vendor, or just plain beats up your robot. Either way, it takes your money. Commerce is fast becoming the driving force for Internet programmers and Web page designers. Organizations interested in protecting their assets hire programmers who understand the needs of commercial enterprises and how to protect them with security techniques. As a VBScript programmer, make sure you understand this concept. Your purpose is to serve the motivating interests of your employer. Most likely, that interest is commerce. Show your employers, or prospective employers, that you know how to conduct business in a safe and secure manner. Suppose that a computer vendor posts a Web page that enables consumers to custom tailor their new computers with specific peripherals, software, and other accessories. To a customer, this idea is intriguing. Now, add security to the Web page and the concept changes from intriguing to a viable incentive for the customer to place an immediate order with a credit card transaction. Adding security helps assuage a customer's fears of some unscrupulous person stealing a credit card number as it travels across the Internet. By eliminating the customer's fear of compromising credit card security, you help the vendor establish an impulse buying center for a several thousand dollar computer system. As this concept becomes more accepted in online commerce, the number of vendors seeking developers capable of implementing secure transactions will rise. Two types of people have an interest in Internet security: those who must protect information and those who want to get it. You can probably learn more valid security information from the criminal hackers than from security professionals. After all, the hacker likes to disseminate information, whereas the security professionals prefer to conceal information. Keep this in mind when browsing

the Internet for additional information about security. This chapter provides information on the prevalent Internet security topics in action today, and those in the design stages for tomorrow.

Transaction Security
A transaction is the process of conducting business. In most cases, such a transaction involves moving something of importance from one location to another. The amount of security that you choose depends on how much value is attached to the items involved in the transaction. If you're sending a message to someone else, the value that you place on the message determines whether you send an open postcard, a letter in a sealed envelope, or perhaps a package with a dedicated courier service. The degree and type of transaction security that you use for sending data over the Internet is much the same as sending a letter. Most electronic mail (e-mail) is much like a postcard. It travels from one location to the next, stopping at various points along the path. Any network administrator could read your message without any resistance or any way for you to detect that it is being read. Should such indiscriminate access to data be unacceptable to you or those to whom you send the data, you might find yourself in need of transaction security. Before deciding on a method of transaction security, it helps to define the elements necessary to secure a transaction. The following list may help you decide what's best for your situation:
q q

q q

q q

q q

Transactions must remain confidential Your transaction should remain private and unavailable to others as it travels the Internet. Encryption is the best way to ensure that your transactions remain confidential. The transaction must retain integrity This means that your transaction arrives in the same state that you sent it. Nothing along the path should alter or affect the contents of your transaction. If you send $10 in a financial transaction, you don't want it to arrive with a zero cash balance. Encryption helps retain integrity. Installing some form of authentication, such as a checksum or digital signature, is also wise. Both the sender and receiver must be accountable Both parties should agree on the transaction and offer some form of acknowledgment when sending or receiving the transaction. Both parties must be authenticated Some communication protocols use a series of Acknowledgment and Negative Acknowledgment codes to communicate the status of a transaction. The codes verify whether the transaction made it in one piece, but don't verify that the right person is sending or receiving the transaction. Authentication ensures that each party is who they say they are.

This following sections in this chapter discuss how encryption technology helps you achieve these goals in your own applications.

Encryption

Encryption is the process of transforming a message so that only the intended receiver can restore the message to its original, readable form. A random pattern can easily scramble a message. However, the problem with random patterns is that because of the unpredictable nature of the scrambling process, nobody, not even the message's originator, knows how to unscramble the message so that the receiver can use it again. A valid scheme must use a regular pattern to encrypt the message so that the receiver can decrypt it. However, such a scheme must retain some secrecy so that others cannot decrypt the message. Regular encryption patterns are called keys. The size and type of a key determines how difficult it is for someone to crack the encryption code and reassemble the message. Keys are bit codes. A computer can easily perform a repetitive search until it finds the correct key to decode the encrypted message. The longer the bit code, the more difficult and time-consuming it is to crack it. The shorter the bit code, the easier it is to crack, especially with the assistance of modern computer technology. Many Internet servers use only 40-bit keys that, although difficult to decipher, are still vulnerable to decoding. A larger bit code increases the number of possible bit combinations and therefore greatly diminishes the likelihood of unauthorized access. Some products use a 128-bit key to make unauthorized decryption practically impossible.

To calculate the number of possible bit combinations in a given set of bits, raise 2 to a power X, where X is the number of bits in the set. For example, a 2-bit set has four possible combinations because 22 = 4. The possible combinations are (in binary notation) 00 01 10 11. An 8-bit set has 256 possible combinations because 28 = 256. A 40-bit set has 1,099,511,627,776 possible combinations because 240 = 1,099,511,627,776.

The United States government considers encryption schemes to be a form of munitions. Therefore, the exporting of encryption-capable applications falls under heavy scrutiny. The government allows as much as 40-bit key encryption for export. Any key using an encryption over a 40-bit code must remain within the United States. Violation of this policy is subject to criminal penalty.

There are two types of keys: symmetric and asymmetric. A symmetric key is one in which the sender and receiver use the same key to encrypt and decrypt a message. Using only a single key is the major weakness of symmetric key encryption schemes. In a symmetric key encryption scheme, the key code must travel unencrypted so that the receiver can use it to decrypt the message. If an attacker gets this

key code, he can decrypt your messages, regardless of how many bits you have used to encrypt them. The United States government defined and endorses the Data Encryption Standard (DES), which is a symmetric, secret-key encryption scheme. Both the sender and receiver must know the same secret key code to encrypt and decrypt messages with DES. The DES standard operates on 64-bit blocks with a 56-bit key. DES operates rather quickly and works well for encrypting large data sets. So far, no one has ever broken into a DES-encrypted file, although many researchers have tried. A pair of researchers proposed a theory that could break the DES encryption scheme, but they still consider DES a secure standard due to the resources and time required to crack a DES-encrypted file. One of these researchers, Adi Shamir, is also one of the creators of the RSA public-key encryption system. The section "RSA Encryption," later in this chapter, covers that encryption system. Asymmetric key encryption schemes use a public and a private key. Anyone who wants to receive an encrypted message must have both keys. The receiver provides the public key, and the sender then uses it to encrypt the message. The only way to decrypt the message is with a combination of the receiver's public and private key. Even the sender can't decrypt the message, because the sender doesn't know the receiver's private key. Asymmetric encryption schemes soon turn into a web of public keys. In small groups, this process is reasonable, but it becomes unmanageable in large environments with many users. Imagine you're in a group with five users. Each has a public key. In order to exchange encrypted documents, you need to have the public key of every user. That draws a line from you to user 1, another to user 2, and so on. Now, each of those other users has exactly the same situation, drawing lines from themselves to other users. One user ends up holding multiple keys, and must know which one to use when sending an encrypted document to someone else. Now, multiply that by a 5000 user corporation and imagine the chaos.

Secure Electronic Transactions


If you have any doubt that electronic commerce drives the need for Internet security, this section should open your eyes. The Secure Electronic Transactions (SET) protocol is a combined developmentincluding Visa, MasterCard, Netscape Communications, IBM, Verisign, SAIC, Terisa Systems, GTE, and Microsoftthat provides a method to secure bankcard transactions over open networks such as the Internet. Previously, these organizations were working on separate technologies to perform the same basic task. You may find old references to Secure Transaction Technology or Secure Electronic Payment Protocol. Many of the overview details seem similar, but the implementations varied. Fortunately, for both developers and consumers, these groups decided to pool their talents to create a single technology designed to secure transactions conducted on public networks.

Visa and Microsoft developed STT as an open specification for the industry. Meanwhile, MasterCard, IBM, and others worked on another open specification for the industry: Secure

Electronic Payment Protocol (SEPP). On February 1, 1996, MasterCard International and Visa International joined together to announce a technical standard for safeguarding payment-card purchases made over the Internet. They call the new specification Secure Electronic Transactions (SET), which combines both efforts.

Earlier sections of this chapter discussed the growing trend of electronic commerce and the need for secure financial transactions. Breaking into an encrypted file is a daunting task, and people always take the path of least resistance. Cracking an encrypted transaction is the modern equivalent of blowing up the bank to steal its money. To say the least, it's not subtle. A criminal must decide if the contents are worth the effort. If the prize inside an encrypted file is nothing more than a collection of movies in AVI format, it's probably not worth the effort required to crack the file. If the prize is a financial transaction, the criminal may decide to expend some time and effort to steal money or credit card numbers. Suppose that an attacker wants to steal your funds. Instead of attacking your secure file, he may instead set up a Web server that claims to represent a legitimate business. With a little creative programming, the attacker's site can let you browse an electronic catalog of goods. After you decide to make a purchase, you engage your super-secret encryption scheme and send off a payment to the server. After a nice run of collecting credit card numbers, the server closes down. You're left anxiously awaiting a package that never arrives. As you wait, the attacker is trashing your credit history. This kind of nightmare is exactly what bankcard holders want to avoid. They already spend millions of dollars to combat credit card fraud. With the aim of fighting such scams, SET has the following objectives:
q q q

Ensuring confidentiality of payment information Authenticating cardholders and merchants Preserving the integrity of payment data

Bankcard providers certainly want to encourage commerce on the Internet. An analysis of past mail order and telephone order transactions shows that customers strongly prefer paying with bankcards rather than with checks, wire transfers, or any other type of payment. Credit cards fit better with the nature of electronic communications than any other payment medium. The SET protocol specifications, like other security specifications, can address only a portion of the protocols necessary for electronic commerce. Standard Internet protocols (such as TCP/IP and HTTP) already exist to provide the transport mechanism, communication services, and application interface necessary for commerce. STT differs from the protocols previously discussed in this chapter in that it concentrates exclusively on the security aspects that pertain to bankcard transactions. The following aspects of bankcard transactions are within the scope of the SET protocol:

q q q q q

The application of cryptographic algorithms, like RSA and DES Credential messages and object formats Purchase messages and object formats Authorization messages and object formats Message protocols between client and server

Clearing and settlement is the process by which a merchant receives payment for a transaction using a bankcard. The merchant authorizes the transaction and then later requests payment from the cardholder's financial institution. Merchants who use the Internet for commerce are subject to the same credit card fraud dangers that occur in other purchase sources, such as telephone orders. The clearing and settlement process differs depending on the card used and the relationship defined between the merchant and the financial institution. As such, SET does not modify the clearing and settlement process. The merchant is responsible for clearing and settling electronic commerce transactions in the same manner in which it processes other transactions. The clearing terms depend upon the merchant's agreement with its bank. SET brings forth a new application of digital signatures by requiring dual signatures. Electronic commerce requires two sets of authorizations. Suppose that you want to send an offer to a vendor to buy an item. You include a digital signature to authenticate yourself as a customer and otherwise validate the message. The same time that you send your message to the vendor, you send another message to your financial institution that authorizes it to release the funds that you specify if the vendor accepts your offer. You need not disclose the details of the offer to the financial institution. All the financial institution needs is your instruction to release funds if it meets a specified condition. To process the offer automatically, the vendor sends a request for payment, including your digital signature, to your financial institution. The financial institution matches signatures. If it verifies that both are the same, it transfers the funds to your vendor. The transaction, from a financial perspective, is then complete. A dual signature concatenates the message digests from your letters to the vendor and the financial institution. SET then computes another message digest from the concatenated result and encrypts it with the signer's private signature key. One key element necessary for authorization is a credential for cardholders and merchants alike. The financial institution provides a credential for cardholders. In theory, you cannot alter these credentials and only the financial institution can generate them. Likewise, the merchant's financial institution issues the merchant's credential.

A credential in this case is a binary file that acts as the bank's seal of approval for financial transactions. The binary file is actually a digital signature like those discussed earlier in the chapter.

RSA Asymmetric Keys


RSA is an algorithm for asymmetric encryption. Named after its inventors Ron Rivest, Adi Shamir, and Leonard Adleman. The algorithm, owned by Public Key Partners (PKP) of Sunnyvale, California, received a patent in 1983. RSA's use is subject to the approval, and possible license, of its owners. Anyone in North America must obtain a royalty-based license from PKP to use the RSA algorithm in a commercial endeavor. Fortunately, PKP usually allows free non-commercial use of RSA for personal, academic, or intellectual reasons, with written permission. The United States government can use RSA without a license, because the algorithm was developed at the Massachusetts Institute of Technology (MIT) with some government funding. The patent does not apply outside North America. RSA is well established as a de facto standard. As the most widely implemented public-key encryption system, it is a safe choice for implementing encryption schemes in applications. RSA's common use makes it easier to exchange digital signatures. This standard is entrenched in the financial transaction protocols being developed for electronic commerce. This endorsement alone confirms that RSA carries much weight as a secure standard.

RSA and DES


RSA is a complement to, rather than a replacement for, DES encryption. Each scheme has benefits that the other lacks. DES is a fast encryption scheme and works well for bulk encryption. Although RSA is fine for encrypting small messages, DES is a better choice for larger files because of its speed. RSA provides digital signatures and secure key exchange without requiring a prior exchange of secret codes. A single user protecting files for personal use probably doesn't need RSA. For such use, a single-key encryption scheme like DES usually suffices because there's no danger involved in passing the key to anyone else. RSA becomes important when you must share messages with others. Combining the two encryption schemes is like sending a coded message in a secure envelope. A typical RSA digital envelope transaction with another party might operate as follows: 1. Encrypt the message with a random DES key. 2. Encrypt the DES key with RSA. 3. Send the combined DES/RSA encrypted document through the Internet. As mentioned before, RSA also creates digital signatures. When authentication is as important as concealment, you must use RSA in place of or in conjunction with DES encryption.

How Does RSA Work?


RSA starts with two large primes: p and q. The product of p and q is n, the modulus. You might find some documentation pertaining to RSA that recommends choosing a key pair with strong prime numbers. A strong prime is one with properties that make the product (n) hard to factor with certain methods.

A modulus is the mathematical process of dividing two operands and returning the remainder.

Factoring is the process of splitting an integer into a small set of integers (factors) which, when multiplied, yields the original integer. Prime factorization requires splitting an integer into factors that are prime numbers. Multiplying two prime integers is easy, but factoring the product is much more difficult. That's why prime integers are such prize candidates for encryption schemes. Reversing the process of multiplication using prime numbers is extremely difficult. This is called a one-way function, one that is easy to perform in the forward direction, but far more difficult to compute in the inverse direction.

Due to new factoring methods, the common knowledge method of choosing strong primes is no longer an advantage. The new methods have just as much success on strong primes as with the weak ones. Another concern with choosing your primes is the size of modulus that you want. There's a bit of a trade-off: a larger modulus creates a more secure encryption scheme, but also slows the encryption process. Choose your modulus length based on your security needs, or perhaps based on the resources that an attacker may use to crack your encrypted message. Here's some research trivia to help guide your decision: Rivest's estimates suggest that an attacker can factor a 512-bit modulus with an $8.2 million effort. If you require a 512-bit modulus, each of your primes should be approximately 256 bits long. Next, choose a number, called e, that is less than the value of n and also relatively prime to (p-1)(q1). Next, find its inverse value, d, (mod(p-1)(q-1)). That means that (ed = 1 mod(p-1)(q-1)).

The variables e and d are, respectively, the public and private exponents. The public key pair is (n,e). The private key is d. You should keep factors p and q confidential, or else destroy them. Before you start writing your own code, pay attention to this next part, because it reveals the Achilles heel of RSA encryption. Trying to determine the private key (d) from the public key combination (n,e) is practically impossible. Now look at those variables (p and q) that you want to hide or destroy. If you factor n into p and q, you can discover the private key (d). The following list shows you how the RSA encryption algorithm flows step by step: 1. Create two variables, P and Q. Create another variable, N. 2. Choose two large prime numbers and assign one to P and the other to Q. 3. N is the modulus of P and Q (n := P mod Q) 4. Create a variable, E. 5. Choose a number to assign to E that is less than the value of N and also relatively prime to the results of the formula ((P-1) (Q-1)). 6. Create a variable, D. 7. Find the inverse value of E with the formula (mod(P-1) (Q-1)). Assign that value to variable D. Keeping in mind how much an attacker would love to have your p and q primes, carefully consider which method to use to generate primes. If you select a predictable pattern, an attacker might duplicate it and render your machinations useless. It's best to obtain random numbers from a physical process. Although some computers use dedicated peripheral cards just for this purpose. One example is the FedWire II system used by many U.S. banks. FedWire II is an encrypted communication network that performs monetary wire transfers between banks and the Federal Reserve. You probably want a less expensive solution. Try timing some of the various input devices connected to your computer (such as your mouse, keyboard, or serial device) and use the time difference between inputs as a random number generator. If you choose an algorithm based on a random seed, try to select a seed that isn't obvious to someone who can duplicate your efforts, or at least select a seed that is truly random.

RSA Authentication
RSA authentication is a specific method for creating a digital signature. A digital signature holds a unique advantage over a handwritten signature. With a handwritten signature, you can alter a

document's contents without invalidating the signature. You cannot do this with a digital signature, because the document's contents comprise the digital signature itself.

A digital signature failure doesn't always mean that someone tampered with your document. If you are transmitting the document over the Internet or other network lines, a digital signature failure may also suggest a corrupted file transfer.

You obtain your digital signature from a message digest. A message digest is the result of a hash function. A hash function is a mathematical algorithm that reads some input data source, usually a message or some kind of document, and returns a compact binary output that represents the source. Some other types of programs, like databases, use hash functions as an index to the data source for quick searches.

A hash function uses a variable-size input and returns a fixed-size string, called the hash value.

Hash functions that are difficult to invert are specifically useful for creating message digests. A message digest is a concise representation of the message used to create the digest. Any change in the message itself yields a different message digest string, thus making it useful as a digital signature. Several well-known message digest functions are in use, but MD5 is perhaps the best function to implement as a digital signature. MD5 is secure, reasonably fast, and publicly available for unrestricted use. ON THE WEB http://ds.internic.net/ds/dspg0intdoc.html For more details on the MD5 function, see RFC 1321 at this Web site. One significant issue with digital signatures is a legal matter rather than a technical one. Digital signatures may not have the same legal status as a handwritten signature. No one has yet challenged the validity of a digital signature in court, so there is no legal precedent. The National Institute of Standards and Technology (NIST) has, however, requested an opinion from the United States General Accounting Office (GAO) regarding the legal status of digital signatures. The GAO opinion is that digital signatures meet the legal standards of handwritten signatures.

Authentication
Authentication is a process that assures a document's recipient of the sender's validity and the document's integrity. The authentication process verifies that a transaction is original and unmodified. The process yields a digital signature created from a message digest, which is a unique string of bits based on the message's contents. A signature is an unforgeable data string that testifies that a specific person created or agreed with the document's contents. A sender creates the message digest and encrypts it with a private key. The message digest accompanies the message. The receiver decrypts the message digest and compares it to the message. If the two agree, the authentication process is valid. You can encrypt and sign a message at the same time. Another authentication process relies on digital certificates. These digital certificates contain the following:
q q q q

A public key A distinguished name (name and address information) Issue data and expiration data The digital signature of a certifying authority (CA)

The CA is a trusted authority, such as VeriSign, that creates digital certificates. The CA generally charges for this service. A CA publishes its public key and Distinguished Name for other people to add to Web browsers or servers as part of their trusted root. Users who want to authenticate a digital certificate use the CA's public key to verify the CA's signature in the certificate.

Microsoft CryptoAPI
As Microsoft started providing Internet development tools, it realized that programmers creating sophisticated communications software needed an application programming interface (API) to provide encryption and secure communications. The result is CryptoAPI, an API that allows Win32 developers to include cryptography technology in their applications. Its goal was to create an API that made cryptographic application development functional, flexible, usable, and exportable for Windows developers. The CryptoAPI uses a modular approach. The actual cryptographic operations are performed by replaceable components known as cryptographic service providers (CSPs). CSPs are dynamic link libraries with associated cryptographic signatures authorizing it for use by the CryptoAPI. Each CSP contains the cryptographic algorithm, but is developed independently of the application. This means your applications can run with many different CSPs, allowing you to choose a CSP that fits the level of security you need without having to modify your application code. The CryptoAPI provides the following services:
q

Digital signatures

q q

Store-and-forward encryption Online encryption

CryptoAPI provides 24 function calls contained under five categories, as follows:


q q q q q

Context management Key generation/management Key exchange Data encryption/decryption Hashing/signature functions

Context management functions connect an application to a CSP. The functions let your applications choose a specific CSP by name, or choose a CSP with a specific functional class. Key generation functions let your applications generate and customize cryptographic keys. You can randomly generate keys or derive them from a password. The functions include support for changing initialization vectors, chaining modes, and other encryption features. Key exchange functions allow your applications to exchange or transmit keys. Encryption keys transmitted outside the CSP are themselves encrypted with the user's public key. They remain so encrypted until they reach the destination user's application. This allows you to transmit keys without compromising them as a security breach to your own encryption techniques. You can use these key exchange functions to implement Private Communication Technology (PCT) or Secure Sockets Layers (SSL) technologies in your own applications. The Data encryption and decryption do much as the titles suggest; they allow you to encrypt and decrypt data. The functions also include support to simultaneously encrypt and hash data. The Hashing and Signature functions allows your applications to compute cryptographically secure message digests based upon data. They also enable you to include digital signatures based upon those message digests. Once signed, anyone possessing the signer's public key can easily verify the signer's identity, or whether something modified the data file. Microsoft licensed its cryptographic technology from RSA Data Security to create the default CSP that will ship with its Win32 operating systems. This CSP supports both public-key and symmetric cryptography. The first version should ship with the Windows NT 4.0 operating system, and then later with a future version of Windows 95. You can find the Microsoft CryptoAPI on Microsoft's Internet Development Toolbox Web site.

From Here...
Encryption is an age-old technology that works quite well. Its application in electronic commerce is still in its infancy, however. Each of the Internet security specifications discussed in this chapter is still under revision. Some products, particularly those from Netscape and Microsoft, already

implement the concepts, even though the specifications are nothing more than working drafts. Perhaps that's why people still don't trust their cards to these schemes. Nevertheless, the market for such technology continues to grow. If you're a programmer who works as an independent contractor, this is an excellent field to enter on the ground floor. With billions of dollars in purchasing power at stake, vendors clamor for space on the Internet. As this happens, they spend a lot of money on developers who can ensure the safety of their dollars, as well as that of their customers. In the meantime, here are some Web sites that may help you find more information:
q q q q q q q q q q q

RSA Data Security at http://www.rsa.com/ Microsoft at http://www.microsoft.com Netscape Communications at http://www.netscape.com The Internet Spec List at http://www.graphcomp.com/info/specs/ InterNIC Specifications at http://ds.internic.net/ds/dspg0intdoc.html Raptor Systems Security at http://www.raptor.com/./library/library.html Stardust Technologies at http://www.stardust.com/wsresource/wsresrce.html WinSock Development Info at http://www.sockets.com/ MasterCard at http://www.mastercard.com Visa at http://www.visa.com Verisign at http://www.verisign.com

In this chapter, we took a bird's eye view of Internet security concepts and techniques. You can browse some of the Web pages listed previously for more information on security topics. After that, perhaps you'll want to try your hand at implementing security in some of the protocols discussed in other chapters of this book.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

Chapter 9 - An Introduction to Distributed Objects


by Michael Marchuk

Software composed of distributed objects is one of the newest genres of application development. Software developers are making use of the ability to add application "components" as they need them through distributed object development models. This chapter exposes you to the basics behind the distributed object models and their uses in Internet application development. Distributed object software development makes use of technologies like Java, JavaScript, ActiveX, and VBScript, which have all been recently introduced as key Internet components. Both Netscape and Microsoft have committed to the distributed object direction by including these technologies into their Internet browsers. In this chapter you learn:
q q q q

The meaning behind distributed objects The basic models used to implement distributed object applications The security implications of distributing application objects The mechanisms that are used to prevent object code tampering or object viruses

Understanding Application Objects


Application objects have been used for a long time. These objects may take the form of reusable code segments, subroutines, DLL code segments, and OLE controls. The more common view from a Windows perspective is that of the Object Linking and Embedding (OLE) controls. An OLE control is a self-contained application that provides specific functionality when called by another application. OLE controls allow various properties and methods by which the data is stored and used between the main application and the OLE control. This type of functionality enables developers to reuse the OLE controls in other applications easily. Some examples of OLE controls include the multimedia control interface (MCI32.OCX) used to manage the interface between an application and a CD-ROM drive or an AVI movie file and the grid control (GRID32.OCX) which is used to handle the spreadsheet-

like interface managing cells and their contents. If you have used Visual Basic or VBA to write applications, you may be very familiar with OLE controls. These control objects provide the functionality from which the application can extend their own usefulness without recreating application code (see fig. 9.1). Since the functionality exists within the OLE control, the developer simply needs to call the functions within the control with the proper parameters to make use of the embedded functions. FIG. 9.1 Applications written to use OLE control objects can make use of the object's functionality easily. The benefits of using controls become apparent when the focus of the development effort is directed away from the controls themselves and onto the functionality that the controls provide. Not only will the developer save time and effort from avoiding the duplication of rewriting control code, but the developer can significantly increase the functionality of the application by making use of properties which may not be essential to the operation of the application but are available through the control object they are calling. For example, a developer may not necessarily build a subroutine to handle interpreting all of the tags in an HTML 3.0 document when the only tag that needs to be used is the title. But if a control object can fit into the application to provide complete HTML decoding, the developer may be inclined to use the other features simply because there is no additional coding required. Control objects are becoming an easy way to develop complex applications in a relatively short amount of time, because the objects provide the framework around which your application can be written. The popularity of control objects is evident with the increase in usage of programming environments like Visual Basic that use control objects to a great extent. The Internet extends this type of object usage through VBScript and JavaScript which utilize standard control objects as well as custom controls to create distributed applications.

Understanding Object Distribution Models


Control objects supplied on diskette with applications make use of the traditional transportation mechanism for distributing programs. However, the Internet is challenging that method by introducing on-demand object distribution and application loading. Web pages sprinkled with scripts add functionality to the static content of an HTML page. The added functionality helps to distribute application logic to the end-user and ease the processing burden on the server. But on-demand control object distribution has its own set of issues. For example, when an object is requested from a distributed application, the application must know where to get the object if it does not exist on the user's workstation. Additionally, because distributed objects are likely to be upgraded or modified periodically, applications which use these objects will need to be able to request the correct version of an object in order to ensure that the proper functionality is present for the program to operate.

This section briefly explains a few distributed object models and how they work. The next section, "Securing Distributed Objects," covers some of the details associated with guaranteeing that a particular object has not been infected with a virus or that the object comes from an unknown source.

COM/DCOM
The Component Object Model (COM) specification was initiated by Microsoft to cover the Object Linking and Embedding programming interface which stresses an open usage of software objects. The object components are distributed and called by an application to perform a particular function. Vendors who supply COM-compliant application objects enable applications that are COMcompliant to make use of the functions within the object. The COM specification permits a handshaking between the application and the objects, which enables the application to make use of the most functionality available in the particular version of the object. The COM specification also requires location transparency for the execution of the object. In other words, an object may be running on the local workstation, or on a server across the Intranet. The application only needs to know how to access the features that the object is presenting and the object only needs to present its functions for the applications to use. The underlying functions within the object may be accomplished in any fashion, as long as they are consistent with this services the object is providing. The Distributed Component Object Model (DCOM) was recently introduced by Microsoft to the Internet Engineering Task Force which manages Internet standards. The DCOM proposed standard establishes a uniform mechanism for building application-level protocols between servers and clients in a distributed environment.

The Distributed Component Object Model Request for Comment Internet standards draft is available at http://ds1.internic.net/internet-drafts/draft-brown-dcom-v1-spec-00.txt.

CORBA
The Common Object Request Broker Architecture (CORBA) is an industry standard distributed object model that is maintained by the Object Management Group (OMG). The OMG established CORBA as a standard in 1991 to enable client applications to find the proper server objects for a particular request. An ORB (Object Request Broker)is the middleware that establishes the client-server connections between distributed objects. Using an ORB, a client application can use a function on a server object, which can be local or over a network. The ORB manages the request and finds an object that can fulfill the request (see fig. 9.2). The client application does not have to know where the object is

located, what programming language it uses, which operating system it is running on, or anything else which is not part of an object's application programming interface. This enables the ORB to provide cohesion between applications on different machines in distributed environments. FIG. 9.2 The ORB facilitates the process of fulfilling an application's object request.

Java/JavaScript
The recent popularity of Java and JavaScript has brought the theory of distributed applications to a new generation of programmers. The basic concept behind the Java operating environment is the compiled "byte-code" which is executed on a remote client within a virtual machine environment. The remote client does not need to have any permanent storage facilities, because the application is downloaded from the server each time it is run. For example, if you want to display fancy marqueestyle moving lights around a picture on an HTML page, you could embed the Java application which manages the marquee lights when the page is loaded. This model of getting the code for the application every time it is run allows the code to remain up-todate and does not require the client to manage any storage space to hold the marquee light application. In addition, the client running a Java application may not be a workstation or PC, but could be an appliance such as a telephone, because the application is running within the standard Java virtual machine environment within the real system environment of the hardware. The virtual machine concept is discussed later in this chapter in the section titled, "Virtual Machines." Java applications can be very large depending on their complexity. Additionally, a large application requires a fast network or a lot of patience on a slow network connection. Because the application must be downloaded each time before it runs, a slow modem connection may cause large delays when using Java applications. JavaScript, on the other hand, is a scripting language that requires the client workstation to have the base JavaScript classes from which the applications may use the various functions. For example, a JavaScript application may make use of an equation that calculates a mortgage payment schedule. The JavaScript application would use the math functions that are part of the JavaScript base classes that exist on the client workstation's hard drive. JavaScript applications are relatively small and read much like Visual Basic source code. Because the application is really a script that draws from the functions already available on the client workstation, the download times and sizes are much smaller than Java applications. To summarize the advantages of Java and JavaScript:
q q q

Java can be used to create complex applications. Java can be compiled into byte-code for fast execution. Java can be used on many different operating systems and hardware platforms.

JavaScript can provide quick and easy access to pre-built Java components which exist within a client's browser.

ActiveX/VBScript
ActiveX is a recent technology offering by Microsoft that extends the OLE control concept a step further into the Internet realm. The ActiveX architecture is designed around the concept that the applications that are downloaded should be installed on the client workstation so that they may be used at a later time without requiring the application to be downloaded again. This mechanism saves download time and increases the application's speed because the object that is downloaded is a natively-compiled application. VBScript is a subset of Visual Basic for Applications which allows ActiveX controls to be called like the OLE controls (OCX) are called from within Visual Basic. This type of mechanism opens up the ability to create interactive web pages to millions of Visual Basic programmers and Microsoft Office users who have created Visual Basic applications. The VBScript source code is embedded into the HTML page like JavaScript, and uses functions from within the VBScript base classes and from within the ActiveX controls which may be downloaded. To summarize the advantages of ActiveX and VBScript:
q

ActiveX objects are natively compiled for a particular platform, allowing them to run faster and provide more functionality than a Java application. ActiveX objects are stored locally after they are downloaded, which makes them available for future usage without the need to re-download them. ActiveX objects are created much like OLE objects, so Visual C++ programmers will be familiar with the development efforts. VBScript uses very familiar Visual Basic coding which allows millions of Visual Basic programmers the ability to start producing VBScript code.

Securing Distributed Objects


Using distributed objects makes a lot of sense when you begin thinking of how the Internet works. The applications that are being written and downloaded by clients do not need a formal installation routine and can be used whenever the need arises. However, like the virus threat that began in the 1980s and is still very prevalent, there is a healthy concern about the security aspects of downloading programs on-the-fly. Security of distributed objects is based on two concepts, trust and isolation. For example, if your friend wrote an application and gave it to you, you would probably feel fairly confident that the application would not contain any malicious code. The same feeling applies to applications that you may purchase from a local retailer or via mail order. There is a certain level of trust that you have put into the sources from which you've obtained the software.

This next section covers the various methods that are used to ensure some level of security when a user runs a distributed application.

Trusting Distributed Objects


The ActiveX method of maintaining security through the distributed objects that are used is by assigning a digital "fingerprint" to create a verified object when it is released. A verified object is one from which a registration number has been obtained through a third-party like VeriSign. That registration is embedded into the object to allow you to trace the author of the object. For example, let's assume a programmer writes an object that can display various obscure graphic image types. In order for others to use this object within their distributed applications, the object must be placed into a location from which it can be accessed. The programmer chooses to place the object into an archive on a server which holds other distributed objects. In order for that object to be accepted, however, the programmer must register the object and provide detailed information like a street address, e-mail address, and phone number by which the programmer can be reached. This registration process provides some assurance that a malicious object, or an object with a serious bug, can be traced back to its author. This also provides a level of comfort to the user downloading the object that the author is responsible for the actions of their code. Now, this registration process will probably not stop the hardened criminal from bypassing these safeguards, but it will curb the flow of amateurs who may see this as an easy way to get noticed. See the section "Code Signing" for more information on the mechanisms involved with this type of security.

Code Signing
The mechanism for maintaining a trust relationship between distributed object developers and end users is by using a mutually trusted third-party. This is done through the use of authoritative digital signatures which are assigned to a registered developer. A certificate authority (CA) holds information which positively identifies the developer and holds the developer responsible for not releasing intentionally malicious programs. Once a developer has signed a legal document that promises to abide by the CA's rules, then the developer will receive a digital certificate which can be used to cryptographically "sign" all of the programs which are released from that developer. The cryptographic signing will ensure that the code is from a particular developer and that the code has not been tampered with since it left the developer's hands. This allows end users to accept code which has been signed by particular CAs which the end user is familiar with and trusts. The digital signature also provides the end user with the knowledge that the developer who signed the code has taken steps to ensure their reputation.

For more information on obtaining a digital ID signature through a certificate authority, check VeriSign's Web site at http://digitalid.verisign.com/.

Isolating Distributed Objects


When an anonymous distributed object is called from an application you are running from within a Web page, you should have a certain level of paranoia regarding the functionality of the application. This is where the second concept of securing distributed objects comes in. By running an application in a contained environment, the objects will not be allowed to run rampant on your workstation and destroy your data. Instead, misbehaved applications may cause the browser to fail or possibly cause the application that was calling the object to self-destruct. Sealing off these unknown applications and distributed objects allows the system to protect itself from the virus-like activities which might be built into the distributed objects. The most common method of creating a contained environment, know as a virtual machine, is explained in the next section "Virtual Machines." Obviously, the security of any system depends on the strength of the mechanisms involved. For instance, the Netscape Navigator version 2.01 contained a bug which could have been used to create a Java "virus" application. Netscape released version 2.02 to correct this fault, but the same type of problem can occur with any browser or operating system. The only way to completely prevent malicious distributed objects from causing damage is by shutting off any distributed application usage. This will obviously remove all of the benefits of using distributed applications. Two methods of preventing damage caused by distributed objects is to enable all of the error-checking and monitoring switches on your current browser and by maintaining the most current browser release which will include fixes for known security holes.

Virtual Machines
A virtual machine is an environment in which applications may run with a restricted access to real system resources. For example, a Java virtual machine includes the ability to allocate memory resources dynamically, but restricts the ability to write to the system's hard drive or to communicate with another process on the system. These types of restrictions allow the end users a sense of wellbeing when they run an application which operates within a virtual machine. The user will not need to worry about a virus infection or a malicious application, because no damage can be done outside of the virtual machine. An additional advantage that a virtual machine carries is the ability to create an environment within any operating system on any platform. A virtual machine is just that, a virtual operating environment that can work the same on every platform. This powerful advantage allows developers the ability to create applications which can literally be run within virtual machines on every platform which is supported. For example, an application written for a virtual machine environment may be run on a computer with DOS or Windows, a Macintosh computer, or even a mainframe. As long as the virtual machine environment is consistent from platform to platform, the application can make the same function calls and operate the same way.

The main disadvantage to using a virtual machine is that the code that is created to run within the virtual machine environment is a compiled "byte-code," which must be interpreted when the program is run. This causes the applications to perform more slowly than natively compiled applications. It is unlikely that the objects running in a virtual machine will be used for computationally complex applications in which the user would notice much of a difference between a native application and one running on a virtual machine.

From Here...
Now that you've had a brief tour of distributed objects and their usage, you'll want to move forward and start to learn about how VBScript can make use of these distributed objects to produce a robust distributed application. You may want to check out these chapters next:
q

Chapter 7, "ActiveX Objects," outlines the various ActiveX components which are available by default within the VBScript environment. Chapter 11, "Designing VBScript Applications," describes the Visual Basic scripting syntax from within an HTML page.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 10 - Embedding Internet Explorer in Your Application


by Ibrahim Malluf

While Internet Explorer is a complete standalone application, it is also an OLE Automation Server and a COM object. This means that you can use the Internet Explorer as an object in your programs from which you can instantiate and manipulate through its automation interface. If you are a VB or C ++ programmer, you can also utilize the WebBrowser object contained within the shdocvw.dll as the foundation for your own customized browser. In this chapter
q q q q

Control Internet Explorer 3.0 You'll be prepared to use Internet Explorer as an application object. Build your own browser After you've read this chapter, you'll be ready to construct your own Web browser.

Controlling the Internet Explorer 3.0 Application as an Application Object


While you could use the VB Shell command to call up the Internet Explorer as a separate application, controlling the Internet Explorer application through OLE automation is a more appropriate approach that gives you direct access to many properties and methods of the InternetExplorer object. In this chapter, Visual Basic 4 will be used to present a very easy example of automating the Internet Explorer through a Visual Basic application. To lay out the form, do the following: 1. Start a new Visual Basic project and save it with the name IEControl.vbj. 2. Add a text box and an array of eight command button controls with the name cmdBrowser

for the command controls. Arrange them as shown in Figure 10.1. FIG. 10.1 This Internet Explorer automation project is being created in Visual Basic 4. 3. From the tools menu of the Visual Basic menu, select the Custom Controls menu item. 4. From the list of custom controls, select the Microsoft Internet and Shell controls. 5. In the General Declarations area of the QueDemo form, add the declaration of the automation server, "Private MyIE as New InternetExplorer." This creates an instance of the Internet Explorer as an OLE automation server within your project. To complete this example, enter the code in Listing 10.1

Listing 10.1 quedemo.frmProgramming the methods and properties of the Internet Explorer Option Explicit Dim MyIE As New InternetExplorer Private Sub cmdBrowser_Click(Index As Integer) On Error GoTo BadcmdBrowser: Select Case Index Case 0 'Open explorer MyIE.Visible = True Case 1 'close explorer MyIE.Visible = False Case 2 'send URL MyIE.Navigate Text1.Text Case 3 'get url Text1.Text = MyIE.LocationURL Case 4 'go back MyIE.GoBack Case 5 'go forward MyIE.GoForward Case 6 'refresh MyIE.Refresh Case 7 'end program MyIE.Quit Set MyIE = Nothing Unload Me End Select

ExitcmdBrowser: Exit Sub BadcmdBrowser: MsgBox Err.Description Resume ExitcmdBrowser End Sub When the project is run, the QueDemo form is displayed, giving the user eight actions to select. By clicking the Open Explorer button, a fully operational instance of the Internet Explorer will be displayed. The user can manipulate the Explorer from either the Internet Explorer itself or from the project form. If the user ends the Internet Explorer from the Explorer's interface, an automation error occurs. You will also get an automation error when trying to go back or forward when there are no pages to go back or forward to. Using this method to provide Internet browsing to your applications is very limited but allows quick implementation. If you are looking for something a little more robust, read on.

Building Your Own Browser


The shdocvw.dll exposes a control called the WebBrowser that can be dropped on your application's form and provides a set of events, properties, and methods that gives you almost complete control over your Web browsing. In this section, we'll build the shell of a browser application that can be easily customized to meet organizational requirements for functionality, security, and so on. Table 10.1 is a table of controls to be placed on the form. Table 10.1 Controls to Place on the Project Form Control ToolBar TextBox ComboBox PictureBox StatusBar Name MyTools txtAddress cmbAddress Description A Win95 common controls toolbar A text box control with the caption "Address:" A style 0 combo box A common dialog box The WebBrowser control A status bar control

CommonDlg cdgFileBox WebBrowser MyWeb Status

WebContainer A picture control with background set to black

Arrange the controls on the frmBrowser.frm as shown in Figure 10.2. In the case of the WebBrowser control, make it a child of the WebContainer picture box control by first selecting the picture box and then drawing the WebBrowser control into it. The txtAddress and cmbAddress controls can be placed anywhere since they will be sized and moved into place by program code anyway. The status bar should have three panels with the last two panels having their Styles set to Date and Time respectively.

FIG. 10.2 Where do the browser project controls go? For the ToolBar control, set the button properties as shown in Table 10.2. Table 11.2 The Button Property settings for the MyTools ToolBar Button Property 1 1 2 2 2 3 3 4 4 5 5 6 6 7 7 8 8 Key Key Style Width Key Style Key Key Key Key Key Setting 'GetFile' 'TextPlace' 4-PlaceHolder 1400 ComboPlace 4-PlaceHolder 'Quit" 'GoBack' 'Refresh' 'GoForward' 'GoHome'

toolTipText 'Get and HTML Document from disk'

ToolTipText 'Close the browser application' ToolTipText 'Go back to previous page' ToolTipText 'Refresh the current page' ToolTipText 'Go forward to next page' ToolTipText 'Go to home page'

At this point, there should be a form with all of the required controls with properties set up properly. I should make it clear here that when this project hasbeen completed, you will have a working browser, but it is not any where nearcomplete enough for distribution and is only a vehicle to demonstrate what can be accomplished. You will have to flesh this project out with appropriate error handling, user interface, and other enhancements by yourself. Included on the CD is a file called clsToolBox. cls that contains some utility procedures that the project requires. Add this file to the project now. There are two public properties exposed by this form, the Location and ShowStatus properties as

shown in Listing 10.2. While not used anywhere in this project, they are included so that you can easily add this form and its supporting clsToolBox class to another project. You can also add other public properties and methods as needed. By setting the Location property to a valid URL, you can cause the results of that URL to be displayed in this form. The ShowStatus properties allow you to read and write to the form's status bar.

Listing 10.2 frmbrowser.frmThe General Declarations and Property Procedures of the frmBrowser Form Option Explicit 'class contains required utility procedures Private clstools As New clsToolBox 'contains the name of the file returned by 'the GetDocumentFile procedure Private strFilePath As String '==============Begin Property Procedures============= Public Property Get Location() As String Location = MyWeb.Location End Property Public Property Let Location(strNewValue As String) MyWeb.Navigate strNewValue End Property Public Property Get ShowStatus() As String ShowStatus = Status.Panels(1).Text End Property Public Property Let ShowStatus(strNewValue As String) Status.Panels(1).Text = strNewValue End Property The next group of procedures are general procedures that provide supporting code to the events triggered by the user or by the browser. The first procedure in Listing 10.3 is the GetDocumentFile() function that returns a Boolean True if the user selected a file and a False if the user cancels. If the function returns a True, then the file path is returned through the function's strFileName argument. The ResizeAll sub procedure maintains the sizing of all of the controls as the user resizes the form or as the WebBrowser control changes size due to URL parameters. We call this procedure from the form's Resize event and from the WebBrowser's MyWeb_OnDownloadBegin() event. This gives the WebBrowser an ugly flicker when a given URL is acted upon, but it was the only solution available with the beta release Internet Explorer 3.0. The final release of Internet Explorer 3.0 is supposed to include an OnWindowResized event that shows some interesting possibilities, but it was not functional as this book went to press.

Listing 10.3 frmbrowser.frmThe General Procedures Code '=================Begin General Procedures==================== Private Function GetDocumentFile(strFilename) As Boolean On Error GoTo BadGetDocumentFile 'assume success GetDocumentFile = True cdgFileBox.Filter = "HTML Documents *.htm|*.htm|All Files *.*| *.*" cdgFileBox.ShowOpen strFilename = cdgFileBox.filename ExitGetDocumentFile: Exit Function BadGetDocumentFile: GetDocumentFile = False Resume ExitGetDocumentFile End Function Private Sub ResizeAll() '============================================ 'resizes all visible components to fit form '============================================ Dim MyHeight As Long Dim MyWidth As Long Dim MyTop As Long Dim MyLeft As Long '----Basic Dimensions----MyHeight = Me.ScaleHeight MyWidth = Me.ScaleWidth '----Calculated Dimensions-----If MyTools.Visible Then MyTop = MyTools.Height '----------Resizing--------MyTools.Top = MyTop mywebcontainer.Move 0, MyTop, MyWidth, _ MyHeight - (150 + (MyTop + Status.Height)) If MyWeb.Visible = True Then mywebcontainer.Visible = False MyWeb.Move 0, 0, _ mywebcontainer.Width - 110, _ mywebcontainer.Height - 110 MyWeb.Container.Visible = True End If Status.Panels(1).Width = MyWidth - 2200

txtAddress.Left = MyTools.Buttons(2).Left txtAddress.Top = MyTools.Buttons(2).Top cmbAddress.Top = MyTools.Buttons(3).Top cmbAddress.Left = MyTools.Buttons(3).Left cmbAddress.Width = MyTools.Buttons(3).Width txtAddress.ZOrder cmbAddress.ZOrder End Sub Public Sub AddToList(MyCombo As ComboBox) Dim MyText As String MyText = MyCombo.Text If Not clstools.IsExactComboMatch(MyCombo) Then If MyCombo.ListCount > 20 Then MyCombo.RemoveItem 1 End If If Len(MyText) > 7 And InStr(MyText, "www.") > 0 Then If Left(MyText, 7) <> "http://" Then MyText = "http://" & MyText End If Else End If MyCombo.AddItem MyText MyCombo.ListIndex = MyCombo.NewIndex Else End If End Sub The last procedure in Listing 10.3 is the AddToList() subroutine. Its purpose is to check the URLs contained in the ComboBox passed as an argument to it for duplicates. If there are no duplicates, it adds the URL to the list. Also if the list has exceeded 20 entries, it removes an entry from the list to keep it at the maximum 20 entries. The subroutine calls a utility procedure from the clsTools object called IsExactComboMatch(). Listing 10.4 contains the event code for the form. The Load Event of the frmBrowser sets the form's caption, adds a URL to the cmbAddress ComboBox, and displays the browser's home page as determined by Internet Explorer's system settings.

Listing 10.4 frmbrowser.frmThe From Events Code for the frm.Browser '==============Begin Event Procedures====================== Private Sub Form_Load() Me.Show

Me.Caption = "Que Special Edition Web Browser" cmbAddress.AddItem "http://www.rt66.com" cmbAddress.ListIndex = cmbAddress.NewIndex MyWeb.Visible = True MyWeb.GoHome ResizeAll End Sub Private Sub Form_Resize() If Me.WindowState <> vbMinimized Then ResizeAll End Sub Private Sub Form_Unload(Cancel As Integer) Set clsTools = Nothing End Sub The form's Resize event calls the ResizeAll() procedure as long as the form's window state is not transitioning to the minimized state. If the ResizeAll() procedure was called with a minimized window, then invalid property errors occur. Finally,being a hopeless paranoid and knowing the OS is out to get me, I make sure that I terminate the clsTools object by setting the object reference to nothing. Moving on to the cmbAddress and MyTools events, we have Listing 10.5.

Listing 10.5 frmbrowser.frmThe Event Procedures for the cmbAddress and Mytools Controls Private Sub cmbAddress_KeyPress(KeyAscii As Integer) Select Case KeyAscii Case 13 AddToList cmbAddress MyWeb.Navigate cmbAddress.Text End Select End Sub Private Sub MyTools_ButtonClick(ByVal Button As Button) On Error GoTo BadMyTools_ButtonClick Select Case Button.Key Case "GetFile" 'go get a HTML file from a local drive If GetDocumentFile(strFilePath) Then MyWeb.Navigate strFilePath End If Case "GoHome" MyWeb.GoHome Case "GoBack"

MyWeb.GoBack Case "GoForward" MyWeb.GoForward Case "Refresh" MyWeb.Refresh Case "Test" MsgBox MyWeb.Location End Select ExitMyTools_ButtonClick: Exit Sub BadMyTools_ButtonClick: MsgBox Err.Description Resume ExitMyTools_ButtonClick End Sub The cmbAddress KeyPress() event checks for a carriage return signaling the end of input and the desire to activate the URL and load the Web browser. The MyTools_ButtonClick event provides the navigational tools that allow you to go back, forward, home, or refresh the HTML document displayed. If you attempt to navigate to a page that doesn't exist (no next or previous page), an error is generated. Those errors are trapped here and displayed in a message box. They are not fatal errors and merely need to be trapped to prevent program crashes. Now we can get to the WebBrowser's events. In the beta version of the Internet Explorer, several of the events were not yet functional, but enough were working that I could make a substantial browser application. Listing 10.6 provides the event code for the WebBrowser control.

Listing 10.6 frmbrowser.frmThe Event Code for the WebBrowser Control Private Sub MyWeb_OnDownloadBegin() ResizeAll End Sub Private Sub MyWeb_OnDownloadComplete() Screen.MousePointer = vbDefault End Sub Private Sub MyWeb_OnNavigate(ByVal URL As String, _ ByVal Flags As Long, ByVal TargetFrameName As String, _ PostData As Variant, ByVal Headers As String, _ ByVal Referrer As String) Screen.MousePointer = vbHourglass End Sub Private Sub MyWeb_OnStatusTextChange(ByVal bstrText As String) Status.Panels(1).Text = bstrText

End Sub In the MyWeb_OnDownloadBegin() event, the ResizeAll procedure is called to counteract the fact that loading a new URL causes the WebBrowser control to be resized to accommodate the size of the HTML document. The ResizeAll procedure provides the mechanism to pull the WebBrowser's size back into conformity with the size of its container, the PictureBox control. In the MyWeb_OnNavigate() and MyWeb_OnDownloadComplete() events, the mouse pointer is manipulated to let the user know that something is happening. In the MyWeb_OnStatusTextChange() event, the user is notified of the WebBrowser's status through the status bar control. One limitation here is that the WebBrowser control does not return any text indicating when the mouse pointer is positioned over a link. All the code is now in place to run the WebBrowser project. Press F5 to run the project. It should look like Figure 10.3. FIG. 10.3 Here's the WebBrowser project running. We have created a minimal Web browser. What can be done with it? Let's take a situation where we only want the users within our organization to have limited access to the Internet. We want to limit this access to the Microsoft.com site for the purposes of research. We don't want anyone cruising the net for entertainment on our time. So built into our organization's browser is code that allows free navigation within Microsoft's environment but not anywhere else. Listing 10.7 adds this functionality. Listing 10.7 frmbrowser.frmLimiting the Browser's Internet Scope Private Sub MyWeb_OnBeginNavigate(ByVal URL As String, _ ByVal Flags As Long, ByVal TargetFrameName As String, _ PostData As Variant, ByVal Headers As String, _ ByVal Referrer As String, Cancel As Boolean) If InStr(URL, "microsoft.com") < 1 Then Cancel = True End Sub All I am doing here is checking the URL for microsoft.com and canceling the navigation event if not found. This is a very simplistic example and should be fleshed out with a little more sophistication that reflects your needs. When the navigation is canceled in this manner, the Web browser generates an error event in the procedure that called the navigate method. You will have to add error-handling code to address this error. Listing 10.8 shows the two relevant procedures in this project modified to handle this error.

Listing 10.8 frmbrowser.frmAdding Error Code to Compensate for the Navigation Method Being

Canceled Private Sub cmbAddress_KeyPress(KeyAscii As Integer) On Error GoTo BadcmbAddress_KeyPress Select Case KeyAscii Case 13 AddToList cmbAddress MyWeb.Navigate cmbAddress.Text End Select ExitcmbAddress_KeyPress: Exit Sub BadcmbAddress_KeyPress: 'trapping fopr the canceled 'navigate method If Err.Number = 287 Then MsgBox "This URL Not Allowed" Else MsgBox Err.Description End If Resume ExitcmbAddress_KeyPress End Sub Private Sub MyTools_ButtonClick(ByVal Button As Button) On Error GoTo BadMyTools_ButtonClick Select Case Button.Key Case "GetFile" 'go get a HTML file from a local drive If GetDocumentFile(strFilePath) Then MyWeb.Navigate strFilePath End If Case "GoHome" MyWeb.GoHome Case "GoBack" MyWeb.GoBack Case "GoForward" MyWeb.GoForward Case "Refresh" MyWeb.Refresh Case "Test" MsgBox MyWeb.Location End Select ExitMyTools_ButtonClick: Exit Sub BadMyTools_ButtonClick: 'trapping fopr the canceled 'navigate method If Err.Number = 287 Then

MsgBox "This URL Not Allowed" Else MsgBox Err.Description End If Resume ExitMyTools_ButtonClick End Sub

From Here...
In the release version of the Internet Explorer there will be more Events wired in and working to give you greater control of the WebBrowser control. Internet Explorer gives you the ability to create custom browsers that fit the exacting needs of an organization's environmentfrom the corporate intranet to Internet access for students in high-school classrooms. We did not show examples of VBScript and Visual Basic interacting with each other here because the Document Object was not functional at the time of this writing. Be sure to watch the Web site related to this book for examples.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 11 - Designing Visual Basic Script Applications


by Yusuf Malluf

q q

q q

q q

q q

Using Visual Basic Script for designing Web applications You can use Visual Basic Script for designing applications inside your Web pages. These applications can be anything from games to displaying today's date and time. Using Dynamic Web Content Static Web pages are a thing of the past. With the introduction of scripting and object capable browsers, one can design highly interactive pages on the Internet without using several mixand-match alternatives. The Internet Explorer 3.0 Object Model The Internet Explorer Object model is one of the entities which is most important to designing your applications. This chapter gives coverage to the object model. Using the ActiveX Controls and the ActiveX Control Pad The ActiveX controls are the other entities which are important to designing you Visual Basic Script based HTML applications. We will cover the intrinsic ActiveX controls as well as some ActiveX controls included in the ActiveX control pad.

From this point, if you have followed the chapters sequentially, you have a pretty good understanding of the concepts of Visual Basic Script. In this case, you have a pretty good understanding of the ActiveX control pad. You have also seen some usage of the ActiveX controls and you have seen many of the principle functions of Visual Basic Script, not to mention several examples. Now the question is, how can I put this all together to design an excellent application for my Web site? This chapter introduces you to the Internet Explorer 3.0 Object model, which is basically what you use to control different objects of the browser, such as the window object, the document object and several others. A brief explanation on objects is provided too, in case you haven't had much experience with them.

Moving From Static to Dynamic HTML Pages


It is possible that you were using the Internet in the time when browsers served very static and unchanging content. These first-generation browsers had a handful of HTML commands for different styles of text and inserting pictures. This was an extraordinary improvement over other Internet

information systems at the timesuch as Gopher. Next came HTML 2.0 and the second-generation browsers that supported forms and the common gateway interface (CGI). CGI was used to process and store the data of the forms that the new model of HTML offered, with the addition to proprietary tags instituted by different browsers. Today, the expansion of HTML 3.0 and third-generation browsers is unbelievable. Many different companies are rolling out their own browsers; these browsers have the capability to serve truly dynamic web content. With scripting capabilities and the ability to insert a plethora of objects into your pages, you can now have more creative control over how your Web pages are presented. Let's move on to how to create these killer applications.

Using VBScript for Designing Web Applications


Before you can understand how to create these Visual Basic Script applications, you must understand a few concepts that you use to design those applications. The most important concept that you may need to understand is how objects work. Understanding how objects are used is a prerequisite to understanding how the Internet Explorer 3.0 object model works, to understanding the ActiveX controls, and understanding how to integrate these two with elements of an HTML page. You also need to have a pretty good working knowledge of Visual Basic itselfspecifically, how events and procedures work. These topics are discussed in this section as well. Remember, objects and Visual Basic Script are closely knit; you must think of designing your applications on a level that considers them both.

Understanding the Basics of Objects


An Object is simply an interactive entity that you can control by its methods, properties and events. A method is a procedure, or rather, a set of instructions which tells the object to perform a certain task. A property is some sort of attribute of an object. An event is when some sort of action happens to the object. Let's take a human for our example object. A human has methods, properties and events. A method might be eating, digestion, gestation, or a number of other processes. A property might be eye color, skin pigmentation or a number of things which describe the human object. An event for a human might be when the human is pushed. Now, in terms of computers, let's take an ActiveX control for an example object. We will use the label object (object and control virtually mean the same thing). The label control consists primarily of properties and has one method. Some of the label control's properties include its caption, its background color, its foreground color, its size and its font. Its method is the About Box method which displays an about box with information about the control when called. An event for the label control is when the mouse pointer is moved over that control. There is a specific tag for inserting objects in an HTML page and this tag is the <OBJECT> tag. This will be covered in the next section.

Using the <OBJECT> Tag


The <OBJECT> tag, as you already know, is used to insert objects of various types in your Web

page, but we will primarily focus on the ActiveX objects. The general syntax for an object tag is: <OBJECT> <PARAM> ... </OBJECT> There are two tags used in this syntax: the <OBJECT> tag and the <PARAM> tag. The <OBJECT> tag is used to define what the object is and any other general attributes related to the object that are called or defined with the <OBJECT> tag. The <PARAM> tag is used to set the different properties of the object specified by the <OBJECT> tag those <PARAM> tags are nested in. The attributes for the <OBJECT> tag are listed in Table 11.1 and the attributes for the <PARAM> tag are listed in Table 11.2. Table 11.1 The Attributes of the <OBJECT> Tag Attribute ID Function Specifies the name of this object in the document. Specifies which class the object belongs to. Can be a uuid (unique universal identifier) or another group of classes such as Java. For ActiveX controls, this is the classid given of that ActiveX object in your system's registry (which is generally the same for all machines which use ActiveX objects). Specifies where the object should get its data from, could also include data for specifying all the classes properties. Specifies what Internet MIME type to use (example: application/x-oleobject would specify an OLE object to be used as code) Specifies how much vertical space to allot to the object's field. Specifies how much horizontal space to allot to the object's field.

CLASSID

DATA

CODEBASE Specifies where the code for implementing the object is. TYPE HEIGHT WIDTH

Table 11.2 Attributes for the <PARAM> Tag Attribute Function NAME VALUE Specifies which property of the Object to utilize Specifies a value to give to the Object property specified by NAME

There are other attributes which are used with the <OBJECT> and the <PARAM> according to the specification, but these attributes are all one needs to use ActiveX and other objects in a page.

Now that we know what attributes are used by an ActiveX control, let's look at an example control. The code in Listing 11.1 is an example of the ActiveX label control. Figure 11.1 illustrates this listing. FIRSTEXAMP.HTM can be found on the CD that accompanies this book.

Listing 11.1 FIRSTEXAMP.HTMThis Is a Simple Demonstration of an ActiveX Object <HTML> <HEAD> <TITLE>The first listing for chapter 12 demonstrates a simple ActiveX control</TITLE> </HEAD> <BODY BGCOLOR="steelblue"> <OBJECT ID="mylabel" WIDTH="100" HEIGHT="51" CLASSID="CLSID:99B42120-6EC7-11CF-A6C7-00AA00A47DD2"> <PARAM NAME="_ExtentX" VALUE="2646"> <PARAM NAME="_ExtentY" VALUE="1349"> <PARAM NAME="Caption" VALUE="This is label 1"> <PARAM NAME="Angle" VALUE="0"> <PARAM NAME="Alignment" VALUE="4"> <PARAM NAME="Mode" VALUE="1"> <PARAM NAME="FillStyle" VALUE="0"> <PARAM NAME="FillStyle" VALUE="0"> <PARAM NAME="ForeColor" VALUE="#000000"> <PARAM NAME="BackColor" VALUE="#C0C0C0"> <PARAM NAME="FontName" VALUE="Arial"> <PARAM NAME="FontSize" VALUE="12"> <PARAM NAME="FontItalic" VALUE="0"> <PARAM NAME="FontBold" VALUE="0"> <PARAM NAME="FontUnderline" VALUE="0"> <PARAM NAME="FontStrikeout" VALUE="0"> <PARAM NAME="TopPoints" VALUE="0"> <PARAM NAME="BotPoints" VALUE="0">

</OBJECT> </BODY> </HTML> FIG. 11.1 This label appears to be nothing but text, but has many uses. Consider Listing 11.1 for a moment. Several attributes are defined for the <OBJECT> tag which gives useful information about the object being used. First the object is named "mylabel," then the width and height properties for the tag are defined, then the control is specified with the CLASSID attribute. The value "CLSID:99B42120-6EC7-11CF-A6C7-00AA00A47DD2" is what identifies the object on your system, through your registry. The nested <PARAM> tags contain the properties of the label object. As you already know, the NAME attribute is used to specify which property to use and the VALUE attribute is used to assign a value to that property. This entire process is automated, as you have read, with the ActiveX control pad which was covered fully in Chapter 3, "Introducing the ActiveX Control Pad." There is a properties window in the control pad editor which allows you to adjust the properties of any control.

Looking Closer at Scripting and the <SCRIPT> Tag


The <SCRIPT> tag was mentioned briefly in Chapter 2, "Review of HTML." The <SCRIPT> tag is where all Visual Basic Script statements go. Several tags (primarily form input controls) and ActiveX controls can access certain procedures (subroutines) of your script based on an event. An event, as mentioned earlier, is when the user triggers some action related to an object. A mouse-pointer moving over a button is an example of an event. Events can be called from the <A>, <BODY>, <INPUT>, and <OBJECT> tags. There are several ways to control the events of these tags. One method of doing this is by using the event as an attribute; another method is using that method in a subroutine. Examine Listing 11.2 (OBEVENTS.HTM can also be accessed off the accompanying CD). Figure 11.2 illustrates this listing.

Listing 11.2 OBEVENTS.HTMThis Listing Demonstrates the Usage of Objects with Events <HTML> <HEAD> <TITLE>This is the 2nd demo, with more functionality</TITLE> </HEAD> <BODY BGCOLOR="slateblue"><BR> <CENTER> <OBJECT ID="MyLabel" WIDTH=215 HEIGHT=93

CLASSID="CLSID:99B42120-6EC7-11CF-A6C7-00AA00A47DD2"> <PARAM NAME="_ExtentX" VALUE="5689"> <PARAM NAME="_ExtentY" VALUE="2461"> <PARAM NAME="Caption" VALUE="Watch me change!!"> <PARAM NAME="Angle" VALUE="0"> <PARAM NAME="Alignment" VALUE="4"> <PARAM NAME="BackStyle" VALUE="1"> <PARAM NAME="Mode" VALUE="1"> <PARAM NAME="FillStyle" VALUE="0"> <PARAM NAME="FillStyle" VALUE="1"> <PARAM NAME="ForeColor" VALUE="#00FF00"> <PARAM NAME="BackColor" VALUE="#DDAADD"> <PARAM NAME="FontName" VALUE="Comic Sans MS"> <PARAM NAME="FontSize" VALUE="12"> <PARAM NAME="FontItalic" VALUE="0"> <PARAM NAME="FontBold" VALUE="0"> <PARAM NAME="FontUnderline" VALUE="0"> <PARAM NAME="FontStrikeout" VALUE="0"> <PARAM NAME="TopPoints" VALUE="0"> <PARAM NAME="BotPoints" VALUE="0"> </OBJECT></CENTER><BR><BR><CENTER> <INPUT TYPE="button" value="click ME to change" onclick="changes" Language="VBScript"></CENTER> <SCRIPT> sub changes MyLabel.Caption="See. . . I TOLD YOU!" MyLabel.ForeColor = "6316128" MyLabel.BackColor = "167111680" MyLabel.FontName = "Arial" end sub sub MyLabel_Click MyLabel.Caption="Watch me change!!" MyLabel.ForeColor = "65280" MyLabel.BackColor = "14527197" MyLabel.FontName = "Comic Sans MS" end sub </SCRIPT> </BODY> </HTML> FIG.11.2 The ActiveX label control is changed by the button control and by itself through the use of events. In this example, an ActiveX label object is used, but some scripting features and some events have been added. First, an ActiveX label control is defined, then a button control is added using the

<INPUT> tag; some events with the scripts have also been used. When the user clicks the button, the label changes. When the user clicks the label after the button has been pressed, the original label returns. Both of these actions are events. When a user clicks the button, an event occurred which caused the label to change. The OnClick attribute in the <INPUT> tag caused that event to trigger. The OnClick attribute itself is an event and its value calls a Visual Basic Script procedure which causes the label to change. The contents of the label are changed back by just using a script and additional attributes to the <OBJECT> tag of the label are not included. In the script used in this page, there are two subroutines. The first subroutine is used by the button control, and the second subroutine is used by the label object to change its contents back. As you notice in the second subroutine, the name of the label object (MyLabel) is followed by and underscore and the name of an event. This means, that when the OnClick event is true (when the event occurs) for the object named, then the statements contained in this subroutine are to be evaluated. With form controls, objects and other entities, you can use their events as attributes if the controls you are using them with supports that event. You can also use the event in a subroutine as well. Table 11.3 lists some attributes to the <SCRIPT> tag. The next section will cover the syntax for using events, methods, and properties of objects in Visual Basic Script.

The ActiveX control pad greatly simplifies the task of assigning Visual Basic commands for different events of the objects and controls on your page, so you can focus more on the design of your application.

Table 11.3 Additional <SCRIPT> Tag Attributes Attribute EVENT FOR LANGUAGE Function Specifies the event (for the object or control specified by FOR) used to invoke the following code encapsulated in the <SCRIPT> tag with these attributes. Specifies which object or control on the page to use the following script for, if the event specified by the EVENT attribute occurs. Specifies which language should be used. The value for this is always "VBScript" for Visual Basic Script or JavaScript for Javascript.

EventName

A pseudonym for an event. Any event for a specified object or control can be used as an attribute for one of the four mentioned tags (<BODY>, <INPUT>, <OBJECT>, and <A>). The value for this event is always a subroutine in both Visual Basic Script and Javascript. You must use the LANGUAGE attribute and whatever event attribute you specify together in the same tag. Some event names that can be used as attributes are listed in Table 11.4. Note that the compatibility of these attributes vary with different objects and controls. Also, this method may not work with some ActiveX controls.

Table 11.4 A Sample Table of Some Events Used for Different Objects by VBScript EventName Function OnClick MouseOver DblClick OnLoad Triggered when the user clicks the corresponding control or object. Triggered when the user positions the mouse pointer over the corresponding control or object. Occurs when the user double-clicks the corresponding object or control. Occurs when a document object or other controls are loaded in the current page.

Visual Basic Scripting


This section's main goal is to familiarize you with some of the elements of Visual Basic Script that you need to know in order to understand how Visual Basic Script works with objects and controls on a page. To that end, this section focuses on the syntax of how to call methods, how events are triggered, and how to set properties for different objects and controls. Setting Properties for Controls and Objects Setting properties for different objects in a page is perhaps one of the simplest tasks to do in Visual Basic Script. The general syntax for doing this is: <SCRIPT> ... ObjectName.property = value ... </SCRIPT> ObjectName is the name or identity of your object specified by the ID or NAME attribute, property is a specific property for the object named by ObjectName, and value is the value that property is set to.

Consider this piece of code from Listing 11.2: ... MyLabel.Caption="Watch me change!!" MyLabel.ForeColor = "65280" MyLabel.BackColor = "14527197" MyLabel.FontName = "Comic Sans MS" ...

It is always possible (especially in the Internet Explorer 3.0 Object model) for child objects (nested objects) to exist. If a specific property is needed of a child object, append a . (period) followed by the name of the child object after ObjectName, then specify the property in the same manner as shown in the syntax (for example: object.child1.value = "some stuff here". object is the name of the object, child1 is the name of the child object and value is a property of the object child1). This method holds true for any number of nested objects, should they exist.

The preceding section of code illustrates several properties used by Visual Basic Script for the object named MyLabel, which is a text label. The first property is the Caption property, set to the value of "Watch me change!!". Next, the properties of ForeColor (text color of the text) and of BackColor (background color of the text) are set, and finally, the FontName property is set to Comic Sans MS. This is how you set properties for any object or control on the page. The properties for ActiveX controls vary from control to control, and the properties for controls specified by the <INPUT> tag are the attributes used in that tag (such as VALUE and NAME). Other tags on the page have properties too, including the document itself, anchors, and other objects described in the Internet Explorer 3.0 object model section. Triggering Events Visual Basic Script is known as an event-driven language. Everything in Visual Basic Script operates by events. Some of the events listed in Table 11.4 work with many controls and objects. There are a few ways for specifying what happens in a script when an event occurs. The following list shows the syntax of three ways for specifying what happens when a certain event is triggered:

Specifying events as attributes: You can specify an event as an attribute of a tag for an object or control on a page. The value of this attribute should be a subroutine which you have already defined inside a Visual Basic Script tag. The LANGUAGE attribute (see the attributes of the <SCRIPT> tag in Table 11.3) must be included as an additional attribute to this tag, if the specified subroutine is to be used. The general syntax is: r <... EventName="method" LANGUAGE="VBScript" ...> where EventName is any valid event for the corresponding object or control and method is the name of the subroutine that is evaluated when the specified event occurs. The LANGUAGE attribute is used to specify which language to use and must be included when an event is specified on a page. Specifying events for an element in a script tag: Using the attributes described in Table 11.3, you can specify, in the <SCRIPT> tag what event of what object to use the following code for. This is useful if you have multiple subroutines and statements outside of subroutines that need to exist in your script. The syntax for doing this is: r <SCRIPT LANGUAGE="VBSCRIPT" FOR="ObjectName" EVENT="EventName"> r ... </SCRIPT> The LANGUAGE attribute is used to specify which language to use (Visual Basic Script of course), the FOR attribute is used to specify the name of the control or object to use the following code for, and the EVENT attribute specifies what event causes the following code to be invoked. Specifying an event by using a subroutine: This may well be the simplest method of triggering an event and executing some code after the event has occurred. This method uses a subroutine with the same name as the object or control you intend to use with an underscore and the name of the event appended to it. The general syntax follows: r <SCRIPT LANGUAGE="VBScript"> r ... r sub ObjectName_ObjectEvent r ... r end sub r ... r </SCRIPT> The actual subroutine consists of two parts: ObjectName, which is the name of the object you wish to use the event for, specified by EventName. When the event specified by EventName occurs for the object specified by ObjectName the statements in the subroutine are evaluated. A subroutine is always the procedure involved when events are used for different objects and controls. However, other procedures and functions can be called from within that subroutine.

The following listing fragments illustrate two of the aforementioned methods in Listing 11.2. Events are specified as attributes, and are also used as subroutines inside the code. Re-examine this listing again: First, look at the button control, specified by the <INPUT> tag. It has the attribute OnClick, which is an event that calls the subroutine changes in the <SCRIPT> section. This event, obviously, is when the user clicks the button. In the subroutine changes several properties of the label named MyLabel are changed, as you can see.

... <INPUT TYPE="button" value="click ME to change" onclick="changes" Language="VBScript"></CENTER> <SCRIPT> sub changes MyLabel.Caption="See. . . I TOLD YOU!" MyLabel.ForeColor = "6316128" MyLabel.BackColor = "167111680" MyLabel.FontName = "Arial" end sub ... Now, examine the second subroutine in the script. Its name is MyLabel_Click. From this, you know that this subroutine is called when the Click event for the object named MyLabel occurs. When this happens, a set of properties for MyLabel are changed. This is the whole logic behind this program. ... <OBJECT ID="MyLabel" WIDTH=215 HEIGHT=93 CLASSID="CLSID:99B42120-6EC7-11CF-A6C7-00AA00A47DD2"> <PARAM NAME="_ExtentX" VALUE="5689"> <PARAM NAME="_ExtentY" VALUE="2461"> <PARAM NAME="Caption" VALUE="Watch me change!!"> <PARAM NAME="Angle" VALUE="0"> <PARAM NAME="Alignment" VALUE="4"> <PARAM NAME="BackStyle" VALUE="1"> <PARAM NAME="Mode" VALUE="1"> <PARAM NAME="FillStyle" VALUE="0"> <PARAM NAME="FillStyle" VALUE="1"> <PARAM NAME="ForeColor" VALUE="#00FF00"> <PARAM NAME="BackColor" VALUE="#DDAADD"> <PARAM NAME="FontName" VALUE="Comic Sans MS"> <PARAM NAME="FontSize" VALUE="12"> <PARAM NAME="FontItalic" VALUE="0"> <PARAM NAME="FontBold" VALUE="0"> <PARAM NAME="FontUnderline" VALUE="0"> <PARAM NAME="FontStrikeout" VALUE="0"> <PARAM NAME="TopPoints" VALUE="0"> <PARAM NAME="BotPoints" VALUE="0"> </OBJECT></CENTER><BR><BR><CENTER> ... sub MyLabel_Click MyLabel.Caption="Watch me change!!" MyLabel.ForeColor = "65280" MyLabel.BackColor = "14527197" MyLabel.FontName = "Comic Sans MS" end sub

</SCRIPT> </BODY> </HTML>

All events have pneumonic names, so it is easy to tell what an event does. For example, the DblClick event is the double-click event.

Calling Methods In this section, you will learn how to call methods from your scripts. This section does not examine procedures in detail; it illustrates general syntax and how to call procedures of objects and procedures you create yourself. A procedure is always a function or a subroutine. To call a subroutine from within your script, use the following syntax: call ProcedureName(arguments) ProcedureName is the name of the method you are calling, and arguments (surrounded in brackets) are any values that are passed to that procedure (arguments for a procedure are not required, unless that specific subroutine or function requires them). As previously mentioned, you always use the subroutine method when events happen to objects. For example: <SCRIPT> ... sub MyObject_Click() alert "This is a subroutine which is called _ when the Click event happens for the MyObject object." end sub ... </SCRIPT> The statements in the subroutine are evaluated when the Click event for MyObject occurs. This would not work for a function, because a function is a procedure which returns a value. Subroutines can return values as well, but the function itself is returned as a value. For example: <SCRIPT> ... y = 2 x = GiveValue(y) alert x ...

function GiveValue(a) GiveValue = a +4 end function ... </SCRIPT> However, different objects do have methods which are functions as well subroutines. Remember, you can also use the same general syntax expressed previously for calling methods of an Object or a control. Listing 11.3 shows an example of a subroutine and a function call in a script, as well as calling a method from the ActiveX Label Object. Figure 11.3 illustrates Listing 11.3. The file, ACTVX12.HTM can be found on the CD that comes with this book.

Listing 11.3 ACTVX12.HTMThis Listing Demonstrates the Use of Procedures in VBScript <HTML> <HEAD> <TITLE>An HTML Document Using ActiveX controls and procedures</ TITLE> </HEAD> <BODY BGCOLOR="mistyrose"> <OBJECT ID="IeLabel1" WIDTH=170 HEIGHT=93 CLASSID="CLSID:99B42120-6EC7-11CF-A6C7-00AA00A47DD2"> <PARAM NAME="_ExtentX" VALUE="3625"> <PARAM NAME="_ExtentY" VALUE="2461"> <PARAM NAME="Caption" VALUE="Click Me"> <PARAM NAME="Angle" VALUE="0"> <PARAM NAME="Alignment" VALUE="4"> <PARAM NAME="Mode" VALUE="1"> <PARAM NAME="FillStyle" VALUE="0"> <PARAM NAME="FillStyle" VALUE="1"> <PARAM NAME="ForeColor" VALUE="#FF0000"> <PARAM NAME="BackColor" VALUE="#373737"> <PARAM NAME="BackStyle" VALUE="1"> <PARAM NAME="FontName" VALUE="Matura MT Script Capitals"> <PARAM NAME="FontSize" VALUE="24"> <PARAM NAME="FontItalic" VALUE="0"> <PARAM NAME="FontBold" VALUE="0"> <PARAM NAME="FontUnderline" VALUE="0"> <PARAM NAME="FontStrikeout" VALUE="0"> <PARAM NAME="TopPoints" VALUE="0"> <PARAM NAME="BotPoints" VALUE="0">

</OBJECT><BR CLEAR="ALL"> <INPUT TYPE="button" NAME="button1" VALUE="Get Value"> Enter Angle: <INPUT TYPE="text" NAME="AngleInpt" VALUE="0" SIZE="10" MAXLENGTH="10"> The Sine is: <INPUT TYPE="text" NAME="SineInpt" VALUE="0" SIZE="10" MAXLENGTH="10"> <SCRIPT LANGUAGE="VBScript"> dim pi pi = 4 * atn(1.0) sub button1_OnClick dim angle, sinangle angle = AngleInpt.value sinangle = getsin(angle) SineInpt.value = sinangle end sub function getsin(angle) getsin = sin((pi * angle)/180) end function sub ieLabel1_Click call ieLabel1.AboutBox end sub </SCRIPT> </BODY> </HTML> FIG. 11.3 This figure illustrates two controls. When the label is clicked the About Box method is called. The input boxes are used to calculate the sine of a given angle (in degrees). Basically how this program works is: when the user clicks on the label, the About Box of that label is shown. When the user enters a number in the first input box which is preceeded by the text Enter Angle and clicks the button, the number is then converted into radians and the sine for that angle is calculated and displayed. There are several methods used in the code; this section discusses them as they appear in the <SCRIPT> tag. The first procedure is called when the user clicks on the button named button1; this happens to be the only button on the page. When this event occurs, a series of methods are called. First, all the variables you are going to use for this program are declared. Next, the value that the user specifies in the input box named AngleInpt is retrieved. Next, a function is called that passes an argument which is the value specified by AngleInpt. This function converts the angle from degrees to radians, then calculates the sine of that angle (radians are the base angle measure for trigonometric

intrinsic functions of Visual Basic Script). That value is assigned to the name of the function (getsin) which then returns the value to the variable we specified it to return to. Finally, this value is displayed in the text box named SineInpt. Simply, the two methods involved in this entire process are the button1_OnClick subroutine (which, if you remember, is called when the user clicks on the button) and the function getsin(angle) (angle is the argument which is used to convert the angle measure into radians). The methods used with the ActiveX label control are very unsophisticated. Basically, there are two methods involved: the one that is called when the label is clicked on (ieLabel1_Click), and the method that is called inside that method (ieLabel.AboutBox(). Methods are usually called from various objects using the following syntax: call ObjectName.MethodName() Remember the call keyword from the former syntax section; its purpose is to call the specified method. ObjectName is the name of the object you wish to call the method for, and MethodName() is the name of the method for that object you are calling. The object name and the called method are separated by a . (period). Also, the brackets immediately following MethodName are not required for a method so long as no arguments are used with the method.

Using the Internet Explorer 3.0 Object Model


This section briefly discusses the Internet Explorer 3.0 Object Model and the various objects associated with it. This section highlights the main portions of the Internet Explorer 3.0 Object model, which includes the Window Object, the Document Object, the Frames Object and a few others. Figure 11.4 shows the hierarchy of the objects used in the Internet Explorer 3.0. FIG. 11.4 This figure illustrates how all the objects of the Internet Explorer 3.0 Object Model are related. The six objects shown are child objects of the document object at the top of the figure. In Figure 11.4, all the objects are child objects of the Window Object. The Window Object represents Internet Explorer and its methods, properties, and events, as well as the 6 following objects in its entirety. The Window Object has several methods, properties, and events. Some of these key methods, properties, and events are listed in Tables 11.511.7. The Window object is the default object; you do not have to append any of its properties or child objects to it in Visual Basic Script. For example, instead of: window.name You could just use: name

Table 12.5 The Properties of the Window Object Property Name Purpose Frames Location Used when there is a frame set in the current document. This property is an array representing the frames on the page. This will be covered in the frames section Specifies the location of the current window. This is identical to the location object which is covered later. Indicates the name of the window the property is in. If it is in a frame, the name assigned to that frame is used. If there are no frames, then this property does not have a value unless you assign it one. Indicates the parent frame or window this property is in. If there is no frame, then this property refers to browser window.

Name

Parent

Table 12.6 Some Key Methods of the Window Object Method Purpose Used to open or close a document inside the current window or another specified window. It has two arguements: the name of the file you want to open and the name of the window you wish to open it in in the form of: window.open(filename,windowname) where filename is the name of the file and windowname is the name of the window you want to put it in. Both arguements are required. Used to specify a pop-up prompt that the user can enter data into. It also has two arguments: the text that describes the prompt and any default text which goes in the prompt in the form of: window.prompt(ExpString,DftString) where ExpString is the text that describes the prompt and DftString is the defauld text in the prompt. Both arguements are optional. If this method is assigned to a variable (such as x = prompt (stuff,more stuff)) then the variable assigned the prompt will receive any data that was entered in the prompt unless cancel was pressed. Used to close the window. Used to navigate the window to another url in the form of: window.navigate(URL). Where URL is the name of the URL to go to.

Open

Prompt

Close Navigate

Table 12.7 Some Key Events of the Window Object Model. Event OnLoad OnUnLoad Purpose This event is triggered when the page containing this event is loaded. This is used in the <BODY> tag as an attribute to call a procedure. This event is triggered when the page containing this event is closed. This is used in the <BODY> tag as an attribute too call a procedure.

Using the Document Object


The Document object primarily deals with the body of an HTML page. It has three child objects: the Link, Anchor, and Form object. Each of these objects are an indexed array of the number of links, anchors and forms found on a document. The Form object further contains the Element object, which is a indexed array of all the objects and controls on the page. Some key properties and methods are listed in Tables 11.8 and 11.9; no events exist for the document object. Table 12.8 Some Key Procedures of the Document Object Procedure BgColor Purpose Used to used to set the background color of the current document. This color can be a #rrggbb hexadecimal number or a valid color name (see Appendix B for details on color names). Used to set the foreground (text) color of the document,in the same manner as the BgColor property. Used to indicate the URL of the document that referred to the page the user is currently on. For example, if some one who accessed http://www.nm.org/welcome. htm from http://www.someplace.com then the referrer property would be http://www. someplace.com, if this property was in the page of the former location. If there is no prior referrer, then the string returned is a NULL.

FgColor

Referrer

LastModified Used to indicate the date of when this document was last modified. Table 12.9 Some Key Methods of the Document Object Methods Purpose Open Used to open the document for purposes of writing additional lines of HTML. Its general format is: document.open(). Used to write text and HTML to the current document and should be called when the document is opened for writing. Its general format is: document.write(somestring) where somestring can be one string, a variable, or several concactenated strings formatted in HTML which are written to the screen. Used to close the document after any document.writes have taken place. The general format is: document.close(). Remember, the ()s do not have to exist after the method if no arguments exist.

Write

Close

Using the Frame Object


The Frame Object is an indexed array of the number of frames on a page. The first frame of the index corresponds to the frame in the uppermost left hand corner of the browser. You can use this object to set or get different URLS of the different frames that are on the page. The frame array is similar to

the window object in that it can use the other objects in the same manner. For example, you can use the location object to get or set the location of the corresponding frame, and you can use the history object too navigate through that frames history.

Using the History Object


The History Object's main purpose is to access the history list of the browser. This history list lists all the places you have visited during your Internet sessions with this version of Internet Explorer 3.0 (beta 2). There are a few properties for this tag, and three methods which are used to navigate through the history folder. Some key properties, and methods are listed in Tables 11.10 and 11.11. The history object has no events. Table 12.10 Some Key Properties of the History Object Property Function Legnth The Length property is used to specify the length or the total number of URLs visited in this sessions history. Currently, the only number that is returned is 0. This will be fixed in future versions.

Table 12.11 Some Key Methods of the History Object Method Purpose Go Forward Used to specify how many times the browser should go forward in the history list, in the format of: history.go(n) where n is the number of the history file to jump to. Used to specify how many times the browser should go forward in the history, in the format of: history.forward(n) where n is the number of times to go forward. Used to specify how many times the browser should go back in the current history of your browser, in the format of: history.back(n) where n is the number of times back the browser should go.

Back

Using the Location Object


The Location Object is used to provide information about the current location of Internet Explorer. Some key properties are listed in table 11.12. There are no events or methods for the Location Object. Table 12.12 Key Properties of the Location Object Property Purpose Href Used to get the URL of the current window, or to give the current window a new URL.

Protocol

Used to retrieve or set the Protocol type (such as FTP or HTTP) of the current document. What is returned or set is the protocal type followed by the colon (the URL ftp://ftp.nowhere.org would return ftp: using this property). Used to retrieve or set the host portion of the URL of the current document along with the port number being used. Used to retrieve or set the hostname portion of the URL. This is exactly the same as the host property, except the port number is not included.

Host Hostname

Using the Navigator Object


The Navigator Object is used to provide application information about the browser. Some of this information includes the code name of the application, the user agent of the application, the name and version of the application. Some key properties are listed in table 11.13. Table 12.13 Some Key Properties of the Navigator Object. Property AppName appVersion UserAgent Purpose Returns the name of the application. Indicates the version number of the current browser. Returns the name of the UA (user agent) of the browser.

appCodeName Indicates the code name of the current browser.

Using the Script Object


The Script Object was covered fully under the "Looking Closer at the <SCRIPT> Tag" section earlier in this chapter.

Using ActiveX Controls and the ActiveX Control Pad


This section describes some of the ActiveX controls you can use with your application and briefly overviews the ActiveX control pad and its usefulness in designing an Application for your Web Page. There are several ActiveX controls which are included with the ActiveX control pad which are dysfunctional or behave in an unusual manner. You can find information about all the ActiveX control's properties, methods and events with the extensive help provided with the control pad. The script wizard also enables you to easily embed scripts in you HTML document that enable you to seamlessly interact with the ActiveX controls or other elements you have defined for a page. The following list describes some ActiveX controls and their usefulness in designing a Visual Basic Script Application:
q

The Label Control: The Label Control is a pretty interesting control. Not only can you set different values to font sizes, captions, foreground and background colors, but you can also set

values for different points on the label which gives the text an irregular "twisted" effect. The Tab Control: By using the Tab Control, you can easily set and present numerous options with a slick "tab" interface as seen with many applications. The Image Control: The Image control is used to specify an image to be put on the page or layout. The Text Box Control: The text box control is virtually the same control as the one specified by the <INPUT> tag. The Button Control: The button control is virtually the same control as the one specified by the <INPUT> tag. The Combo/Drop-down List Controls: The Combo/Drop-down List Controls can contain a list from which you can select multiple entries, or a drop-down menu from which the user can choose options. These controls are similar to the controls specified by the <SELECT> tag. The ActiveX Layout Control: This control is the most important control for designing your Visual Basic Script applications on your Web page. With it, you have absolute control over the layout of your page. Formerly, all blank space beyond two spaces in HTML was considered "white space" and was collapsed accordingly. This ActiveX control actually references a file with all the ActiveX controls on this layout and any code associated with them.

From Here...
In this chapter, you have learned the bare essentials of designing a Visual Basic Script application. You now have an understanding of how objects and their events, methods and properties work. You now know how to use Visual Basic Script to call procedures based on different events that occur for an object, and you are familiar with how to call and define procedures. You've also learned about a few ActiveX controls which can help you design your application. Remember, there are many more ActiveX controls in the ActiveX control pad than are mentioned here, but some are defunct due to licensing problems with Internet Explorer 3.0 beta 1, which will be resolved in the next release. There are over 2,500 commercially-available ActiveX controls. In the chapters that follow, you will be provided with an extensive overview of the syntactical elements of the Visual Basic Script language, and a comparison to other Visual Basic family languages and Java script. Some of these chapters include:
q

Chapter 14, "Comparing Scripting Languages," discusses the differences between Visual Basic Script (VBScript), Visual Basic for Applications (VBA) and Visual Basic (VB). Chapter 15, "VBScript Data Types and Variables," begins the long chain of chapters that explain the different elements of Visual Basic Script, including Variants and Data types, Procedures, Operators and other elements of the Visual Basic Scripting language. Later chapters in Part 5 cover the multimedia aspects of the Internet, such as Active VRML and serving multimedia content across Web servers.

| Previous Chapter | Next Chapter |

| Table of Contents | Book Home Page | Buy This Book |


| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

Chapter 12 - A Simple VBScript Page


by Ron Schwarz

In this chapter
q q

q q

q q

q q

Visual Basic Basics Visual Basic (VB), and Visual Basic Scripting Edition (VBS, or VBScript) are very similar, but there are some key differences. In this chapter you learn some rudiments to bring you up to speed. Script-Enabled Web Pages Several elements come into play when you create a VBS-enabled web page. This chapter brings them together. HTML and Controls Learn how to insert HTML and ActiveX controls onto a simple page, and add scripting to tie them together. Creating a Working Page Once you know the basics, it's easy to create a script-enabled page, and understand how and why it works.

When you complete this chapter, you'll have a good grasp of what VBS is, and how to use it. You'll have the foundation required to grasp the information provided in the rest of this book. At that point, you should have a "feel" for VBS, and be able to rapidly pick up the more weighty information that follows. Although you will create some working VBS pages in this chapter, you will not find HTML covered to any great extent. HTML is covered in greater depth in Chapter 2, "Review of HTML." This chapter is a full-immersion in VBS, and VBS alone.

Coming Up to Speed with Visual Basic


If you're familiar with Visual Basic, you may want to skip ahead to the next section, "Identifying the Important Differences Between VB and VBScript." If, however, You're new to VB, take a moment

here to bone up on VB essentials. This short primer will help you understand a few important VB principles. Visual Basic is a programming language that features a visual IDE (Integrated Development Environment) which is used to create Windows applications. In VB, you create "Forms," which contain "Controls," and associated code. A VB Form is a window. (A VB form is related in name only to an HTML form.) When you write a VB program, you begin by placing controls, such as Labels, TextBoxes, and Command Buttons on a Form. Form creation is interactive, and very easy. You select controls from a toolbox, and place them on the form. You use the mouse to position and size them, and set their properties from the Properties window, which is a list of properties and values. After you create an object (a form or a control) you set its Properties, and enter event code, and nonevent program code. (Simply double-clicking a form or control will bring up the editor, with the cursor positioned in an automatically created procedure skeleton for the selected object.) At this point, it might be good to remind yourself that we're discussing VB, and not VBS. The reason for this will become apparent when we begin to discuss VBS.

Properties, Events, and Methods In Visual Basic, most objects (such as Forms and Controls) have three key features: Properties, Events, and Methods. A Property controls a characteristic, such as size, color, contents, or position. Events are things that occur while the program is running. Examples are mouse clicks, keystrokes, and form resizing. Event Procedures are blocks of code that are automatically executed when the associated event happens. For example, when the mouse is clicked over a form named Form1, the Form1_Click procedure will be executed. You can also have Sub procedures and Functions that are not associated with events. These routines must be accessed by other codethey will not execute automatically. Methods are instructions to objects. When you invoke a method, you are telling the object to execute a specific set of instructions. Examples of Methods are Print, Refresh, Show, and Hide. These principles all carry over to VBS, even though their actual implementation is quite different.

Visual Basic code is located in either the General or Events sections of a Form. (Code Modules are similar to Forms, but contain only a General section, and have no visual interface.) The General section consists of two parts. The first part is the Declarations section, which contains non-executable code, such as variable and API call declarations. The rest of the General section contains procedures that are not attached to events. An example of a procedure in the General section would be a routine that centers your form on the screen. Such a procedure could be called from anywhere, and is not directly attached to any one specific event. The Events section of a Form contains Sub procedures that are connected to events. When you click a Command Button, for example, any code in its Click event (such as Command1_Click) will execute.

Identifying the Important Differences Between VB and VBScript


There are three main areas in which VBS differs from VB. These are the development environment, the instruction set, and the user interface. At this time, it might be good to point out that VBS is not a new version of VB, nor is it a general purpose programming language. While you may be able to port certain routines from a VB app to a VBS script, you will not generally be able to port most entire applications to VBS, barring superhuman effort far beyond the point at which the law of diminishing returns has been invoked. VBS is designed to make Web pages interactive and intelligent. By leveraging your VB skills, you'll be able to get up to speed quickly. Although you may have to make a conscious effort to remember that a VBS-enabled Web page is not a VB application, you'll find that the possibilities, especially when using VBS in conjunction with the powerful new HTML Layout features, to be endless.

Development Environment
When Microsoft first announced VBScript, it had no IDE. All coding, control creation and placement everythinghad to be done in code, and all code had to be created with an ASCII text editor, such as Notepad. Now, the ActiveX Control Pad makes creation and maintenance of VBS pages nearly painless. Like "real" VB, VBS pages can be designed interactively and visually. The IDE provided with the ActiveX Control Pad is very similar to the one in VB, and you'll have no problem transitioning to it if you're at all familiar with VB. Still, there are differences. Perhaps the most notable are the lack of a Run Mode, and the lack of a Debugger. (Remember, you're not creating programs, per se, but Web pages, and the "run environment" of a Web page is a Web browserso, the final product of your efforts, for all its amazing power and flexibility, is not a program in the literal sense; it requires a specialized environment (such as the Internet Explorer), in order to run.)

In HTML, you're working with a document, rather than a VB-style "form." The browser receives the page as a stream of data, and formats it as it displays it. If you change the width of the browser window, in most cases, you'll also be reformatting the contents of the page. As a result of this inherent difference from the VB form model, on-screen control placement is essentially determined by control declaration context. Where you "create" your controls determines where they will be placed in the document when it's displayed. As limiting and restrictive as this sounds, you can do quite a bit by carefully constructing your HTML and using advanced features, such as frames. When you are script-enabling existing HTML pages, this is probably what you'll find yourself doing most of the time. However, when creating new pages, you will be wise to consider doing most, if not all of your development within HTML Layout Style Pages.

See "Core HTML Components," [Ch 2]. See "Introducing the ActiveX Control Pad," [Ch. 3] See "Creating a Standard HTML Page," [Ch. 4] See "Creating an HTML Layout Page," [Ch. 5]

HTML Layout Style Pages provide a very close approximation of the Visual Basic Form modelyou can place, position, and size ActiveX controls on a page anywhere you choose, without any regard for HTML stream-of-text issues. And, you can set properties by using a Properties window, just like you can in VB. Finally, you can use a powerful Script Wizard to manage event code and method insertion.

Instruction Set
VBS is a subset of the Visual Basic language. Many statements, features, and functions you may be accustomed to using in VB are not available. Some are missing due to security considerations (you wouldn't want to have critical files on your local machine corrupted or deleted simply by clicking a link on a Web page, for instance), and others are unimplemented to keep the "footprint" small. You can work around some of the differences (for example, you can use the ElseIf keyword to compensate for the lack of a Select Case structure, and you can use multiple arrays instead of using typed record variables), but others may very well present impenetrable barriers. There is, for example, no direct file I/O available. This means you won't be able to use any sequential, binary, or random file I/O in your scripts. The specific differences in instruction sets are covered in greater detail in later chapters. For now, be aware that there are differences, many of which are non-trivial.

User Interface
VBS provides a high degree of flexibility and functionality. However, unless you are using HTML Layout Style Pages, it is important to keep in mind the fact that the underlying container is still an HTML Web page, and is not a VB form. Much of the "look and feel" of a VBS-enabled page is determined by (and, limited by) HTML factors. Elements such as toolbars, menus, MDI forms, multiple windows, and standard graphics methods are for the time being beyond the province of VBS scripting. (However, it is possible to implement many of these features by using ActiveX controls by keeping a watchful eye on the market, you will quite likely to find controls appropriate to the task at hand, as new ones are constantly being developed and released.) As HTML Layout Style Pages become more of a standard, you can expect demand for (and proficiency in) "traditional" HTML pages to rapidly diminish. Still, it's good to learn as much as you can, because they will be with us in one form or another for some time, even as they are superseded by the newer standard. Users who have used a variety of Windows apps, and are familiar with existing Web browsers, will have little difficulty making the transition to VBS-enabled pages. Users who are new to Web browsers, and users whose exposure to Windows apps is limited to Web browsers (of which there are quite a few) can expect to experience a bit of a learning curve. This will be ameliorated by virtue of the ease of use these pages provide.

Creating a VBS-Enabled Page


A VBS-enabled page consists of a mix of HTML blocks and/or HTML Layout declarations, Control declarations, and VBS scripts. (Strictly speaking, Control and Script blocks are also HTML, but we are now examining the differences between HTML code and VBS code.) HTML is a fairly crude language (it is essentially a top-down text formatter), and one advantage you have over a "pure" HTML programmer is the fact that much of the HTML functionality can be done more simply in VBS. Still, you'll need to learn some HTML basics, and this section will give you what you need to get started. HTML itself is be covered in greater detail in Chapter 2, "Review of HTML."

HTML Syntax and Statements


If you've used WordPerfect in the past, you're probably already familiar with the most noticeable characteristic of HTML tagspaired commands. Most HTML commands are used in pairs. For instance, if you wanted to center a line of text, you'd precede it with a <Center> command (or "tag") and place a </Center> command at the end. (The "/" in the second command designates it as the closing half of a command pair.) Everything inside the block is centered, even if it requires multiple lines of text. Because HTML is designed to be formatted on-the-fly by the browser, whitespace generally is meaningless. Carriage returns, tabs, and spaces are "eaten" by the browser, in the absence of specific

formatting commands. (This affects control, as well as text placement.) Therefore this block: <Center>Simple HTML Command Demo</Center> is functionally identical to this block: <Center> Simple HTML Command Demo </Center> Next, we'll examine a few HTML statements. <HTML> The <HTML> statement is used at the beginning and end (as </HTML>) of a page. It tells the browser that everything in the resultant block is HTML code and text. <Head> The <Head></Head> section exists primarily for purposes of source code organization. As a rule, you should place non-displayed parts of your HTML page in the <Head> section. This includes VBS scripts, but not control declarations. <Body> The <Body></Body> block is the counterpart to the <Head></Head> block. Place your displaying elements here, such as text, links, and controls. <Title> The <Title></Title> block defines a block of text, which is placed in the title bar of the browser. It is similar to a VB form's Caption property. <Hn> The <Hn></Hn> block defines a text style used for headers. <H1> is the largest, <H2> is the next smallest, and so on. (<H6> is the smallest.)

<Script...> <Script...> and </Script> tags are used to mark off your VBS scripts. Their use is discussed further on in this chapter in the section labeled "Script Blocks." <Input...> The <Input...> tag is used to declare HTML controls. Its usage is explained later on in this chapter in the section labeled "Buttons." <Object...> The <Object...></Object> pair is used to declare ActiveX controls, and is described later on in this chapter in the "Declaring the Controls" section. <!...> Prefacing any HTML tag with a "!" changes it into a comment, similar to Rem or [sp] in VB. <!-- ... --> You can mark several lines with the Extended Comment tags. These are open-ended (no closing ">") at the start, and close-ended at the end. All lines in between will be converted to comments, if your browser cannot execute them. This can be used to hide your <Script> blocks from displaying as text on browsers that cannot execute them. They will still not execute, but, they will at least not show up on the users' screens.

The tag for comments and extended comments is the same: <!... >. (Note the exclamation point.) The dashes (--) are not required but do add readability. Hence, the following listings are syntactically identical: <! This is a single line comment > <!-- And so is this -- > <! This is an extended (multi-line) comment. Some browsers improperly interpret comments that span more than one line, so this form should be avoided. >

<A HREF=...></A> The <A> (Anchor) tag is generally used to designate a link to another URL. The format is: <A HREF="http://url.address"></A> <P> <P> is the Paragraph command. When you want to insert a carriage return in the flow of text (which also determines control placement), insert a <P> command. This command is different from most HTML statements in that it is not part of a command pair. There is no closing </P> statement, because <P> does not create a block; it merely inserts a line break wherever it appears. <Center> <Center> and </Center> create a block of centered text. All text between them is centered. Placing <P> paragraph markers inside a centered block will insert line breaks, but will not turn off centering. The same applies for other HTML formatting command pairs, which are covered in more detail in other chapters.

Control Declarations
As discussed earlier, there is no visual "drag and drop" means for placing controls on Web pages when using VBS. Instead, controls are embedded in pages by means of declaration statement blocks. There are two types of controls: HTML controls, and ActiveX controls. Each type is declared using its own syntax, which we will examine in this section. HTML Intrinsic Controls HTML has a number of built-in controls, including equivalents to the Command Button, OptionButton, CheckBox, ComboBox, and TextBox that are used in VB programming. Although they offer similar functionality, there are differences in usage. ActiveX Controls ActiveX is the name that Microsoft has given to 32-bit custom controls contained in .OCX files. They are the successors to the venerable .VBX controls, which were designed for earlier (16-bit) versions of Visual Basic. A wide selection of ActiveX controls are available, providing nearly limitless potential. We'll examine two (Label and Timer) that are primarily intended for use with the Internet Explorer. Once you learn the techniques involved in embedding them in HTML, you'll be able to make use of others as the need arises.

Script Blocks
All VBS code is contained in Script blocks. These are HTML blocks beginning with <Script> (see following code segment), and ending with </Script>. You can have more than one block, however, at least the first one must specify VBS as the language you're using, as in: The LANGUAGE= clause tells the browser that this script contains VBScript code (as opposed to another scripting language, such as JavaScript). Following scripts on the same page can simply begin with <Script>. The <Script> tag has other options; we'll examine some of them later on. Code contained in a VBS script falls into one of three categories: initialization code, event code, and non-event code. Initialization Code Initialization code is code that executes when the Web page loads, without requiring any action on the user's part. If you're familiar with VB, you're familiar with the Form_Load event, which executes when a form is loaded into memory, and the Sub Main procedure, which will execute automatically when a program is loaded (if the project has the "Use Sub Main" option selected). VBS initialization code is similar; however, it actually hearkens back to pre-VB days. Earlier versions of BASIC, such as QuickBasic and PDS 7.x were (like VBS) non-window-oriented languages. Although they had Sub procedures and Functions (like VB), they also had the ability to place executable code outside of any named procedures. In VB, only non-executable code, such as variable and API declarations, can be placed outside of named procedures. VBS will allow you to place executable code there; however, there are a few caveats, and doing so is not encouraged unless you have a specific reason, and are prepared for some extra work. You may find, for instance, that when you set properties of ActiveX controls in your initialization code, not all of them are in fact assigned, yet no errors are generated. Event Code Just as in "regular" VB, objects used with VBS can generate events. And, like VB, event code will automatically execute when the associated events occur. The ActiveX Control Pad can, like the regular VB IDE, create event headers for you. Non-Event Procedures In addition to writing procedures that execute automatically when objects generate events, you can also create procedures that can only be invoked by code. The format is the same as that used with event procedures, with the following exceptions: you can create Functions, as well as Sub procedures (Functions return a value in their name, and are invoked on the right side of the equal sign), and, you can declare your own parameter lists.

Before you can create your first page, you will need to an understanding of data types, and controls. The next two sections cover this material.

Introducing Data Types


VB has a variety of data types, including user-defined typed structures. VBS, however, has only one data type: the Variant. Fortunately, a variable of Variant type can contain nearly any type of data, and treat it as a subtype. So, you can store strings, numeric values, dates, and so forth. You can use the VarType function to determine what subtype is in use in a particular variable, and, there are several conversion functions built into VBS, which make it possible to convert data from one subtype to another. These features are described more fully in Chapter 16, "VBScript Data Types, Variables, and Structures." A short summary of several common data types follows: Type Description Boolean Either returns True or False Byte Unsigned Integer limited to a range of 0 255 Integer Signed integer, range is 32,768 32,767 Single Single-precision floating-point subtype; can hold negative values from 3.402823E38 to 1.401298E-45, and positive values from 1.401298E-45 to 3.402823E38. Double Double-precision floating point subtype; can hold very large (or small) values Date Value contains a numeric representation of a date String Can hold a string up to about 2 billion characters; fixed-length strings are not supported

Introducing Controls and Events


Now that we've had an overview of controls and events, let's dig in, and actually create some pages that use them. We'll begin with a simple page that demonstrates the use of HTML intrinsic controls, and then we'll create another page that uses ActiveX custom controls. We'll also have a chance to see how both event and non-event code are created and used.

Creating Your First VBS-Enabled Page


In this example, we'll use the Button and Text HTML intrinsic controls. We'll also take a sneak peek

at the underlying IE (Internet Explorer) object architecture, which provides access to and control of many of the built-in features of the IE. The first example is only slightly more ambitious than a "Hello World" first effort; it uses a few lines of HTML and a short script to determine the current URL, and, accept input for a new one. Then, it changes to the new location when a Button control is clicked. Here's the full listing:

Listing 13.1 HTML.HTMSimple HTML Control Example <HTML> <TITLE>Here And There</TITLE> <p> <INPUT TYPE=BUTTON VALUE="Where am I?" NAME="cmdWhereAmI"> <INPUT TYPE=TEXT NAME="txtWhereAmI" size=100> <p> <INPUT TYPE=TEXT NAME="txtWhereAmIGoing" size=100> <INPUT TYPE=BUTTON VALUE="Where am I going?" NAME="cmdWhereAmIGoing"> <SCRIPT LANGUAGE="VBScript"> Sub cmdWhereAmI_OnClick 'Event generated when Button is clicked txtWhereAmI.Value = Location.href 'Load Text control with current location End Sub 'End of event procedure Sub cmdWhereAmIGoing_OnClick 'Event generated when Button is clicked Location.href = txtWhereAmIGoing.Value 'Set new location, from Text control contents End Sub 'End of event procedure </SCRIPT> </HTML> Startup This example begins with three simple HTML statements: <HTML> <TITLE>Here And There</TITLE> <P>

The first line is the standard HTML openerit tells the browser that what follows (up to the closing </HTML> at the end of the page) is HTML code. (Even though VBS Scripts are not strictly speaking HTML code, they are contained within <Script> blocks, which are HTML.) The next line creates a Title which will be displayed in the browser's Title bar. (In Visual Basic, the corresponding element is a form's Caption property.) The third line marks a new paragraph. This causes an empty carriage return to be inserted, to leave a little whitespace at the top of the page. Controls The next few statements include several <Input...> tags. The <Input...> tag does not have a closing tag; this is because the declaration information is contained within the actual tag, and no closing tag is required. <Input...> is used to declare an HTML Intrinsic control that is used to interact with the page. The TYPE= parameter declares which control (for example, Text or Button) will be used. Remember, this is HTML, not VB (or even VBS), so where we declare the control determines its actual physical placement on the page. If you declare it at the top of the page, it appears at the top; if you declare it in the middle, it appears in the middle. (Using the HTML Layout Page features provides a powerful mechanism for dealing with this, and once you gain proficiency with VBS, you'll probably want to use it, and the ActiveX Control Pad for most serious development.) The first control declaration line creates a Button control, and assigns it a Name and Value. <INPUT TYPE=BUTTON VALUE="Where am I?" NAME="cmdWhereAmI"> After we declare the TYPE= as BUTTON, we need to assign two other properties: VALUE, and NAME. VALUE is the same as the Caption property in Visual Basic. Whatever you assign as the VALUE of a Button control will appear on the button. In this case, the button will say "Where am I?" The NAME property is identical to the Name property in Visual Basic. It assigns a name to the control. Whenever you reference a control in code, you refer to it by its NAME property. In addition to this fairly straightforward declaration, it is possible to use more complex declarations. This is described in detail in Chapters 9, "An Introduction to Distributed Objects," and 21, "VBScript Forms, Controls, and Managing Transactions."

The HTML Button control is the HTML equivalent for the Visual Basic CommandButton

control, which is itself simply the standard Windows command button.

The next line creates a Text control, and assigns it a Name and Size. <INPUT TYPE=TEXT NAME="txtWhereAmI" SIZE=100> Like the Button control, the Text control has a NAME property, which is used to reference the control in code. The Text control also has a SIZE property, which is used to assign a width for the control when it's created in the browser. HTML controls use a simplified series of properties when compared to Visual Basic. If you're a VB user, you may be surprised at the lack of Height and Width properties. The height is determined automatically, and the width is expressed in the maximum number of characters you want to allow in the control. In this case, we assign 100 characters as the maximum. Text controls also have a VALUE property, which corresponds to the Text property in a Visual Basic TextBox control. If you assign any text to the VALUE when you declare the control, it will appear in the control when the control is created in the browser. Likewise, any time you assign text or a string to the VALUE in code, it will replace any existing contents with the new text. To determine text the control contains, you read the VALUE property.

The HTML Text control is similar to the TextBox control used with Visual Basic. It's a window that the user can type in, and it can also be pre-loaded with text. Unlike its Visual Basic counterpart, it has no MultiLine propertythis means that it can only accept a single line of text. (For MultiLine text entry requirements, you can use the TextArea HTML Intrinsic control.)

The next three lines add another <P> paragraph break (to provide some more whitespace, and, assure that the next two controls start on a new line) and two more controlsanother Text control, and another Button control. At this point, the HTML part of the page is complete (with the exception, of course, of the closing </ HTML> tag at the very end of the page). If you placed the </HTML> tag after the control declarations, you'd see the page in all its glory, just as it will appear after you add the Script to enable it. However, it will be brain-dead; you'll be able to type in the Text controls, and click the Buttons, but since there is no code to deal with those properties and events, nothing will happen. The next section details the simple script that enables this sample to actually do something.

Code The actual script is contained in a block of matching HTML tags. The <SCRIPT LANGUAGE="VBScript"> tag marks the beginning of the script, and the </SCRIPT> closes it. Everything between these tags is VB, not HTML.

Listing 13.2 HTML.HTMEvent Code for HTML Control Example <SCRIPT LANGUAGE="VBScript"> Sub cmdWhereAmI_OnClick 'Event generated when Button is clicked txtWhereAmI.Value = Location.href 'Load Text control with current location End Sub 'End of event procedure Sub cmdWhereAmIGoing OnClick 'Event generated when Button is clicked Location.href = txtWhereAmIGoing.Value 'Set new location, from Text control contents End Sub 'End of event procedure </SCRIPT> The code in Listing 13.2 contains two event procedures. The cmdWhereAmI OnClick Sub procedure is automatically executed when the button named cmdWhereAmI is clicked by the user. (Similar behavior rules apply to the cmdWhereAmIGoing_OnClick procedure.) The first procedure sets the Value property of the txtWhereAmI Text control to the current value of the href property of the Location object. This results in the Text control displaying the URL for the current page. The second procedure changes Location.href to the contents of txtWhereAmIGoing.Value, which causes the browser to load the page at the URL contained in the Text control. To try out the example, load the CD that accompanies this book, and navigate to the icon for HTML. HTM, then double-click it. (You will need Internet Explorer 3.0 or higher installed on your machine; if you haven't already installed it, do so before trying any of the examples in this book.) Figure 13.1 shows what you'll see when you run the program contained in Listing 13.2, and click the button captioned "Where Am I?" FIG. 13.1 Here and There (HTML.HTM)

Using ActiveX Controls


From an implementation perspective, the same general rules that apply to HTML controls apply to ActiveX controls. The main difference is declaration style. ActiveX controls are more powerful and flexible than intrinsic HTML controls, and, their declaration is more complex too.

It is important to remember that ActiveX control declarations take place in "HTML space," rather than inside a <Script> block. As a result of their mixed heritage, they require setting a combination of HTML properties and ActiveX properties. Because it is possible for properties from one context to have names similar to different properties in the other context (such as the properties relating to size and alignment characteristics), it is necessary to keep track of which is which when assigning values to them.

In the ActiveX control example that follows next in this chapter, you'll use two controlsa Timer, and a Label. At the time this book went to press, the Internet Explorer 3.0, as well as development tools such as the ActiveX Control Pad were still in pre-release form. It's likely that you'll have these controls automatically installed by either of them, or, you can get them from the ActiveX Gallery, at:
q

http://www.microsoft.com/activex/controls/

You'll also find several other useful ActiveX controls available at that URL. Using the Timer Control The inTimer (Internet Explorer Timer) control is similar to the standard Timer control that is used in VB. It provides an Interval property, and has a Timer event. The setting in the Interval property tells the Timer how often to fire its Timer event. You enter the number of milliseconds you want to time, and when that time has elapsed, the Timer event occurs. (If you enter 1000, the event will fire once every second.) If you set the Interval to 0, the event will never occur. (The Timer control also has an Enabled property. If you set it to False, it will have the same effect as setting the Interval to 0.) Using the IeLabel Control The IeLabel (Internet Explorer Label) control is similar to the standard Label control that is used in VB. There are two principal differences: first, the IeLabel control is an ActiveX control (rather than a built-in control, as is the case in VB). Second, the IeLabel control can be set to display its text at any

angle (for example, it can display text diagonally, vertically, upside down, or anywhere in between), whereas the VB label control can only display its caption at 0 degreeshorizontal. It is important to note that the IeLabel control itself does not change angleit is only the text within the control that is rotatable. Therefore, the control needs to be set to a sufficient height to contain the full length of the text it contains, at whatever angle is used. The display angle is set with the Angle property. 0 degrees results in standard, horizontal display of text, the same as a standard label control. The control's display moves counter-clockwise according to the value placed in the Angle property. So a setting of 90 degrees causes the text to run vertically, starting at the bottom. Figure 13.2 shows the Angle property setting in the ActiveX Control Pad (described in Chapters 3-5). In this figure, the Angle property is set to 45, and the control can be seen to have its text display set to a 45 degree angle. FIG. 13.2 Setting the Angle Property The IeLabel control has several other properties, including: Property Caption Description Text that is displayed in the control

FontName Name of font used to display text Alignment Aligns text within the control Height Width ID Height of the control in pixels Width of the control in pixels Name by which you refer to the control in code (same as Name property in VB)

The ActiveX Control Pad, when installed, provides another label control, which although unable to rotate text, does provide the unique ability to enter text directly into the control. (When you install the ActiveX Control Pad, you will have a wide selection of controls available, including a TextBox that also allows direct text entry.) Being able to insert text directly into a control when you are designing a form makes it very easy to place content on pages.

Creating Your First ActiveX Page


This example demonstrates the basic elements required in a VBS-enabled Web page using ActiveX controls. You'll create a page that contains the Timer and Label controls, and uses event and nonevent procedures. The complete source for the ActiveX example appears in Listing 13.3, and is contained on the CD accompanying this book in the ACTIVEX.HTM file.

Listing 13.3 ACTIVEX.HTMThe Complete ActiveX Example <HTML> <HEAD> <Center><h2>ActiveX Controls Example</h2><Center> <SCRIPT LANGUAGE="VBScript"> Dim Direction sub lblRotate_Click PrepareRotation "Wheee!" 'call procedure that gets it started end sub Sub tmrTimer_Timer If Direction then lblRotate.Angle=lblRotate.Angle-10 Else lblRotate.Angle=lblRotate.Angle+10 End If If lblRotate.Angle=0 then 'when horizontal, left to right tmrTimer.Interval=0 'shut off timer lblRotate.Caption="Click Me!" 'restore label End If End Sub Sub PrepareRotation (CaptionText) lblRotate.Caption=CaptionText 'set label Direction=Not Direction 'reverse direction tmrTimer.Interval=18 'start timer End Sub </SCRIPT> </HEAD> <P> <BODY> <Center> -----|

<OBJECT ID="lblRotate" WIDTH=151 HEIGHT=151 ALIGN=CENTER CLASSID="CLSID:99B42120-6EC7-11CF-A6C7-00AA00A47DD2" CODEBASE="ielabel.ocx"> <PARAM NAME="Caption" VALUE="Click Me!"> <PARAM NAME="Angle" VALUE="0"> <PARAM NAME="ForeColor" VALUE="#000000"> <PARAM NAME="FontSize" VALUE="24"> <PARAM NAME="FontBold" VALUE="1"> </OBJECT> |----</Center> <OBJECT ID="tmrTimer" WIDTH=60 HEIGHT=49 CLASSID="CLSID:59CCB4A0-727D-11CF-AC36-00AA00A47DD2" CODEBASE="inTimer.ocx"> </OBJECT> </BODY> </HTML> As with the previous example in this chapter (HTML.HTM, under "Creating Your First VBS-Enabled Page"), this example begins with a standard <HTML> tag. This time, however, we're including a <Head> tag, so as to better conform with coding standards, which suggest placing all scripts in the <Head> section of the page, and all displayed elements in the <Body> section. Note that for modern browsers, these conventions will have no effect on display or execution of scripts. Still, HTML is far from a readable language, looking in its raw form more like ancient GWBASIC code than a modern programming language like Visual Basic, so, anything that enhances your ability to understand code after it's been written should be utilized. And, segregating VBScript code from the page proper is a good first step. Here are the first three lines of the example: <HTML> <HEAD> <Center><h2>ActiveX Controls Example</h2><Center> The <H2> (fairly large heading) line is also placed in the <Head> section as per standard practice. (See Chapter 2, "Review of HTML," and Appendix B, "HTML Reference," for more on HTML.) Having said all this, we're now going to (apparently) break with this pattern, and examine the example in a seemingly random pattern. There is a method to the madness, however; it's called HTML. It's because of the vagaries of HTML, which require declarations to be placed as a hodgepodge scattered throughout the document, that we have to examine it this way. (Scripts are placed ahead of content, and controls are embedded in content. Before you can understand scripts, you need to understand controls.)

Designing the Layout


After creating the HTML skeleton, the first stage in creating a page is layout design. Remember, we're not in VB anymore, so it's not a simple process of dragging controls around on a form. All positioning is determined by placement in the text (and to a lesser degree by factors such as <Center> tags and Align attributes), and size is determined by setting properties in HTML code. (Of course, when you're using HTML Layout Pagesdiscussed in Chapters 3-5you are free of HTML limitations, and you can work in a manner nearly identical to VB.)

Declaring the Controls


Declaration of ActiveX controls is handled differently from declaration of HTML intrinsic controls. However, they are still declared using HTML tags; they are not declared inside of VBS scripts. And, unless you're using the ActiveX Control Pad to create HTML Layout Pages, they are also subject to the rules concerning positioning on the page: where they are declared in code determines where they appear when the page is displayed. Here's the first declaration encountered in the ACTIVEX.HTM example. It creates an instance of the IeLabel (Internet Explorer Label) control: <OBJECT ID="lblRotate" WIDTH=151 HEIGHT=151 ALIGN=CENTER CLASSID="CLSID:99B42120-6EC7-11CF-A6C7-00AA00A47DD2" CODEBASE="ielabel.ocx"> <PARAM NAME="Caption" VALUE="Click Me!"> <PARAM NAME="ForeColor" VALUE="#000000"> <PARAM NAME="FontSize" VALUE="24"> <PARAM NAME="FontBold" VALUE="1"> </OBJECT> The IeLabel control is used to place text on an HTML form. It also accepts mouse events, and, can display its output at any angle. The first thing you may notice in this section of the example is the <Object...> open-ended tag. HTML intrinsic controls are declared with the <Input...> open-ended tag, followed by their type, and other HTML properties. ActiveX controls, on the other hand, are declared as Objects, and require additional information. The IeLabel control declared here contains a mix of HTML and ActiveX properties.

HTML properties are defined with a simple assignment statement. The property name is to the left of an equal sign, and the value is on the right. It is important to place them inside the opening <Object... > tag. Note the > after the align=center assignment. The HTML part of the declaration, including setting of HTML properties, takes place within the opening <Object...> tag itself. The ActiveX properties are placed after the <Object...>, but before the </Object> closing tag (see Table 13.1). Confused yet? Here's the format:
q

<Object HTML Declarations [HTML Property Assignments]> ActiveX Property Assignments </Object>

Because this declaration is all HTML code, it can be placed on a single line or broken into multiple lines at your discretion. The HTML part of the declaration contains entries for CODEBASE, CLASSID, ID, WIDTH, HEIGHT, and ALIGN properties. Other controls (or this control in other applications) require additional properties, however, the ones used here are fairly universal. Table 13.1 ActiveX Properties Part Description

Points to the filename of the .OCX containing this control (This info is buried deep in your Windows Registry, and can be retrieved, and pasted into an HTML or HTML Layout Page document with the CODEBASE="IeLabel.ocx" ActiveX Control Pad (described in Chapters 3-5). This property is also used to point to a URL containing a control that can be automatically downloaded to the user's machine. See "Using Objects in HTML Pages," in Chapter 12, "Designing VBScript Applications." Must point to this control's ClassID in the Registrythe ClassID can CLASSID="CLSID:99...D2" be retrieved, and pasted into an HTML or HTML Layout Page document with the ActiveX Control Pad (described in Chapters 3-5). ID=lblRotate WIDTH=100 HEIGHT=100 ALIGN=CENTER The name you'll use for this control in your scripts This control's width in pixels in the browser This control's height in pixels in the browser This control's alignment on the text line in the browser

The other thing you've probably noticed is that the ActiveX property assignments are a bit more complex then their HTML counterparts. The <Param...> tag is used to hold all information for a single declaration. This tag is similar to the <Object...> tag in that it contains declaration information within the tag, but it is different in that it has no counterpart to the </Object> tag. The assignment is in the format name="PropertyName" value="PropertyContents". Note that the

property name must be delimited by quotation marks. The timer control (InTimer), is declared similarly to the the label control; being a different type of control, it uses different properties, but the format is the same, as it is for all ActiveX controls. Here's the relevant section of ACTIVEX.HTM: <OBJECT ID="tmrTimer" WIDTH=0 HEIGHT=0 CLASSID="CLSID:59CCB4A0-727D-11CF-AC36-00AA00A47DD2" CODEBASE="inTimer.ocx"> </OBJECT> This declaration only contains HTML property assignments. We set its ActiveX Interval property in VBS code in the "Writing Event Handlers" section of this chapter. We set its Width and Height to 0, since it's an invisible control, and we don't want it to consume any more HTML space than necessary.

Script Block Declaration


<SCRIPT LANGUAGE="VBScript"> Dim Direction Here, we declare the beginning of our Script block. We also create a script-level variable with the Dim Direction statement. This variable is available to all procedures in our script. (Scoping issues are discussed in the next section of this chapter, "Writing Event Handlers".)

Writing Event Handlers


Event handlers are contained inside a <Script> block. (Event handlers are Sub procedures that automatically execute whenever the specified event occurs. They are covered more extensively in Chapter 19, "VBScript Event Programming.") The first event handler in the script deals with the Click event of the Label control. Because the ID of the control was set to lblRotate, the event handler Sub procedure is named lblRotate_Click. (Event handlers begin with the name of the control, and use an underscore to attach it to the name of the event.) This is the actual event code from ACTIVEX.HTM: sub lblRotate_Click PrepareRotation "Wheee!" 'call procedure that gets it started end sub This procedure contains the Click event for the lblRotate control. In this case, we simply use it to call

the PrepareRotation non-event procedure, which is discussed later on in this section. This code executes when you click on the label control, and starts the process that makes the label rotate on screen. Here's the code that executes after it's called by the click event: Sub PrepareRotation (CaptionText) lblRotate.Caption=CaptionText 'set label Direction=Not Direction 'reverse direction tmrTimer.Interval=18 'start timer End Sub The PrepareRotation Sub is called from the lblRotate Click event, which also passes it the CaptionText parameter. Although the call that invokes this routine passes a string literal (text contained in quotation marks), here it is converted to the CaptionText variable, because it's declared as a parameter in the Sub declaration. This routine also uses the Direction variable, which is available because it was declared at the Script level, rather than declared inside another procedure. (A variable's scope is generally determined by where it is declared. If it is declared inside a script, but outside any procedure in that script, it is available to all procedures in all scripts. If it is declared inside a procedure, it only exists within that procedure.) This is the place where we set the timer control's Interval property, which tells the control to begin its countdown to firing its Time event. We have set it to 18 milliseconds. (When it is set to 0, which is its default, the event never fires.) Next, the event handler for the Time event of the Timer control (IeTimer) is added. Here's the complete event routine: Sub tmrTimer_Timer If Direction then lblRotate.Angle=lblRotate.Angle-10 Else lblRotate.Angle=lblRotate.Angle+10

End If If lblRotate.Angle=0 then 'when horizontal, left to right tmrTimer.Interval=0 'shut off timer lblRotate.Caption="Click Me!" 'restore label End If End Sub The tmrTimer event procedure fires each time the interval assigned to the timer control's Interval property transpires. The code in this event procedure does a fair amount of work. It contains two If/ Then blocks (described in Chapter 18, "VBScript Control of Flow and Error Handling"). The first one tests for the direction of rotation. If it's True, it decreases the value of the Angle property of the label control by ten degrees; otherwise, it increases it by ten degrees: If Direction then lblRotate.Angle=lblRotate.Angle-10 Else lblRotate.Angle=lblRotate.Angle+10 End If The second If/Then block determines when to stop moving: If lblRotate.Angle=0 then 'when horizontal, left to right tmrTimer.Interval=0 'shut off timer lblRotate.Caption="Click Me!" 'restore label End If When the Angle property of the label control equal 0 (indicating that the text is at a horizontal, left-toright orientation), it shuts off the timer by setting its Timer property to 0, and, restores the label's caption to its original contents. Listing 13.4 contains the complete ActiveX example page. Locate the ACTIVEX.HTM example on the CD, then double-click its icon to load it into your browser. You'll see a label captioned "Click

Me!" When you click the label, its caption changes, and it begins to rotate in a clockwise direction. When it has completed 360 degrees, it stops, and its caption is restored. If you click it again, it rotates again in the opposite direction. If you click it while it is rotating, it immediately reverses direction. Here's how it will look after you load it (see fig. 13.3): FIG. 13.3 ACTIVEX.HTM Example And here's how it will appear right after you click the label (see fig. 13.4): FIG. 13.4 ACTIVEX.HTM Example, in Motion While this demonstration doesn't accomplish any real work, it does demonstrate how just a few lines of VBS code, combined with a couple of control declarations, and a handful of HTML code, can automate a Web page. We've placed the VBS script code in the <Head> block, although it will work fine in the <Body> too. By placing it all in the <Head> section, we free up the <Body> for control declarations (remember, where we declare them determines where they appear), and text. This makes formatting the actual page much simpler, as the HTML source will more closely resemble the final output in the browser.

Testing the Page


Before a page is published it needs to be tested. You'll probably want to do most of your initial testing locally (rather than over the Internet, or on your Intranet server) unless you have a high-speed network connection and tools to make upload relatively transparent. Local Testing Local testing is fairly painless, since it essentially consists of saving the HTML file with your text editor, then either double-clicking its icon, or clicking the Reload button in your browser (if it's currently loaded from a previous test). There are a few caveats, however. If your page includes links to other pages or files, you have to make sure that the links are either absolute links (fully qualified URLs), or, if relative links, are duplicated on both systems (your local machine and the remote host on which the page will ultimately reside) in the exact same structure.

Relative links are links that point to a file in a directory that is relative to the current

URL. Absolute links point to a complete URL. This is a relative link: <A HREF="/pages/page1.htm"><B>First Page</A></B> And this is an absolute link: <A HREF="http://www.nethawk.com/~rs><B>Home Page</A></B> Note that the relative link doesn't include a host nameit only includes a path, and file name.

Relative links are generally preferred because it is easier to port a page from one machine or path to another, but you must make sure to port all files that are referenced, and keep them in the same path relative to the original. If you keep all related files in the same directory as your page, you're set just copy them all together. If you include them in a tree inside your working directory, it's fairly trivial to duplicate the tree on the target machine. If, however, you are referencing lateral branches and facing the task of duplicating massive and/or complex directory structures on other machines, you may want to consider editing your page to use a more concise structure. As with most programming issues, there are tradeoffs, and no two situations are exactly alike. If you are aware of the considerations from the outset, you can craft your pages in such a way as to minimize porting headaches later on. Remote Testing Unless you are developing your pages on the same machine that will serve as their HTTP server, you need to transfer them before they can be accessed by Internet or Intranet users. As flawlessly as they may perform after extensive local testing, you still need to run them through their paces after you place them on the server. Subtle errors, usually related to link names, frequently fail to be detected during local testing.

From Here...
For more information on HTML programming, check out A Beginner's Guide to HTML, at the following URL:
q

http://www.ncsa.uiuc.edu/General/Internet/WWW/HTMLPrimer.html

Also, check out these other chapters for additional information:

q q q

q q

See Chapter 2, "Review of HTML," for a discussion of general HTML programming issues. See Chapters 3-5 for information on the ActiveX Control Pad and HTML Layout Pages. See Chapter 12, "Designing VBScript Applications," to learn details of script and object integration. See Chapters 16-21 for extensive information on the essentials of the VBScript language. Refer to Que's Special Edition Using HTML for an exhaustive study of HTML.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 13 - Comparing VBScript, VBA, and Visual Basic


by Ron Schwarz

This chapter addresses the differences you'll encounter when coming to VBScript from a background in one of the "traditional" VB dialects (VB/VBA).
q q q q q q

q q

VBScript For VB Programmers Find out the VB features that are not supported, or behave differently in VBScript. Syntax Differences Learn how to deal with Declaration and Language constraints. Design Interface Issues The ActiveX Control Pad is an excellent tool for developing VBScript Web page applications and content, but it's different from the VB IDE. Find out how this impacts your coding efforts. User Interface Issues VBScript does not create stand-alone applications. Well-designed script-enabled pages can help alleviate the differences. Find out how in this chapter.

Overview
Because VBS is a subset of VB, the bulk of the information provided in here consists of differences mainly differences of omissionas documented by Microsoft at the time this book goes to press. (Some of this may change eventuallythe VBS specifications have changed more than once since work began on this book, but are expected stabilize shortly.) Syntactical differences, covered in Table 13.1, Declaration Issues, and Table 13.2, Language Issues, are only part of the picture. If you're going to excel in what you're doing, you need to learn the nuances of the platform and accommodate yourself to it. Trying to "force-fit" either existing code or existing skills to a new environment is tantamount to the backwoods axiom that advises, "Don't force it, use a bigger hammer!" Even if you do succeed in fitting the square peg to the round hole, neither you, nor your users are apt to be particularly satisfied with the results.

Therefore, it's an absolute necessity that you gear yourself to the language (VBScript) ,the development tools at hand (ActiveX Control Pad), and the presentation medium (Internet Explorer). If you're a VB programmer, you can probably remember muddling through the documentation, the IDE, and the language, making small headway until things suddenly "clicked," and it started making sense. This event marked the beginning of your ability to "think in VB," and you can expect a similar illumination after playing with VBS and the Control Pad for a while. Naturally, you will be able to leverage a considerable measure of your existing skills and language. But, it will quickly become apparent that VBS has its own gestalt. It's not too different from situations that occur with spoken language: Cantonese and Mandarin are both "Chinese," but fluency in one does not equate to fluency in the other. So it is with VBS and the other dialects of VB. You'll find some of the differences maddening at first, but the frustration will diminish as you begin to work instinctively. There are two main reasons for omitted functionality. The first consideration is security (it would be poor form to make it easy for unscrupulous individuals to harm users who stumble upon their websites), and "weight" (because of issues such as download time and memory footprint, VBS is designed to be a "lightweight" implementation of the language).

Declaration Comparison
Table 13.1 covers the declaration changes documented by Microsoft. If you're experienced with one of the other dialects of VB (VB or VBA) you should take the time to familiarize yourself with the differences now, to avoid frustration later on. Table 13.1 Declaration Issues Declaration Declare Property Get Property Let Property Set Public (variables) Private (variables) Issues DLL API calls are not implemented due to security considerations, and because VBScript is intended to be a cross-platform language. (Windowsspecific API calls would fail on a browser running on a non-Windows OS.) Not applicable due to absence of Class creation support in VBS. Not applicable due to absence of Class creation support in VBS. Not applicable due to absence of Class creation support in VBS. Not currently supportedconflicting information available. May be implemented in final release. Not currently supportedconflicting information available. May be implemented in final release.

Static ParamArray Optional New Array function Option Base Private (procedures) Public (procedures)

Use global variables when you need to retain contents between invocations of a procedure. Optional arguments not legal. Optional arguments not legal. Not possible to create new objects. Only legal to create aliases to existing instances of objects. Not supported. Use explicit assignments of each element of an array to load with values. Not supported. All arrays have starting subscript of 0. Not currently supportedconflicting information available. May be implemented in final release. Not currently supportedconflicting information available. May be implemented in final release. You cannot use the Dim Array(LowerBound To HigherBound) form of the Dim statement. All arrays begin with a 0 subscript. You can create a multidimensional array, but all dimensions must begin with an implied element 0. Constants are not supported in VBScript. Use variables, and for convenience, make their names all uppercase, with words separated by an underscore, in other words, MAX_USER_COUNT. Note that this will not make a variable into a constantyou will not be protected from inadvertently changing the value of the variable. It is strictly a means for identifying variables that are being used as ersatz constants. The only built-in constants currently implemented in VBScript are True and False. The As keyword is not supported because in VBScript all variables are of Variant type. It is likewise illegal to append a type-declaration character (such as !, @, #, $, %, &) to a variable or literal. Hence, both VehicleYear% and 1967% are illegal.

Dim (arrays)

Const

Built-in Constants

Dim X As

While not all VB funtionality is supported in VBScript, implemented features are fortunately highly compatible with their VB counterparts. This behavior carries over to most language elements, covered in the next section, "Language Comparison."

Language Comparison
Table 13.2 lists the changes in language elements at the time this book goes to press. There are significant differences between VB/VBA and VBScript. The changes are essentially changes of ommissionwhile you will need to learn what to avoid, you won't have to relearn any implemented features, since syntax remains consistent. Table 13.2 Language Issues

Term Add Count Item Remove ! DoEvents For Each...Next GoSub ... Return GoTo On Error GoTo On ... GoSub On ... GoTo Line Numbers, Labels With ... End CCur CVar CVDate Format Str Val Type ... End Date Statement

Explanation User-defined collections are not supported in VBScript. User-defined collections are not supported in VBScript. User-defined collections are not supported in VBScript. User-defined collections are not supported in VBScript. (for Collections) User-defined collections are not supported in VBScript. Not supported. Not supported. Determine actual quantity being counted (i.e., array UBound), and use a For..Next loop structure instead. Not supportedline labels are not supported in VBScript. Not supportedline labels are not supported in VBScript. Not supportedline labels are not supported in VBScript. Not supportedline labels are not supported in VBScript. Not supportedline labels are not supported in VBScript. Not supported in VBScript. (Line Labels are not be confused with Label controls, which are implemented via ActiveX controls.) With Not supporteduse fully-qualified Object.Property names instead. Not supported (Currency subtype not implemented in VBScript). Not supported, all variables are Variant in VBScript. Not required because there is a built-in Date subtype in VBScript. Was only included in VB4 for backward-compatibility reasons. Not supported. Use String manipulation functions to build formatted strings as a workaround. Not implemented in VBScript. Not implemented in VBScript. Type Typed records are not implemented in VBScript. The Date function is implemented in VBScript, but the Date statement is not. (The function returns the current date; the statement sets the system clock.) The Time function is implemented in VBScript, but the Time statement is not. (The function returns the current time; the statement sets the system clock.)

#Const, #If...Then...#Else Conditionals are not supported in VBScript.

Time Statement

Timer

The Timer function is not implemented in VBScript. This should not be confused with the Timer control, which is implemented (via an ActiveX control). The Timer function returns the number of seconds that have elapsed since midnight; equivalent functionality can be derived by using the date/time math functions for whatever purpose the Timer function would have produced (i.e., start/end time logging). Not implementedVBScript does not offer DDE support. Not implementedVBScript does not offer DDE support. Not implementedVBScript does not offer DDE support. Not implementedVBScript does not offer DDE support. The Debug object is not implemented in VBScript because there is no means to execute a script within an IDE. (The ActiveX Control Pad provides a development environment, but it does not support running scripts within itself.) Not implemented in VBScript. Inapplicable in non-standalone (i.e., browser-hosted) applications. Not implemented, because there is no debug object in VBScript. There is no means to execute a script within an IDE. (The ActiveX Control Pad provides a development environment, but it does not support running scripts within itself.) Not implemented in VBScript; line numbers are not supported in VBScript. Old-style error-handling keyword is not implemented in VBScript. Use the Error object's Raise method instead. Not implemented in VBScript. On Error Resume Next is the only errorrecovery structure available in VBScript (besides the Error object). Not implemented in VBScript. On Error Resume Next is only errorrecovery structure available in VBScript (besides the Error object). Not implemented in VBScript. On Error Resume Next is the only errorrecovery structure available in VBScript (besides the Error object). No file I/O statements or functions are implemented in VBScript due to security considerations. No file I/O statements or functions are implemented in VBScript due to security considerations. No file I/O statements or functions are implemented in VBScript due to security considerations. No file I/O statements or functions are implemented in VBScript due to security considerations. No file I/O statements or functions are implemented in VBScript due to security considerations.

LinkExecute LinkPoke LinkRequest LinkSend

Debug.Print

End

Stop

Erl Error On Error ... Resume Resume Resume Next Open ... Close Get/Put Input # Print # Write #

Financial Functions GetObject TypeOf Clipboard Collection

No financial functions are implemented in VBScript. Not implemented in VBScript due to security considerations. Not implemented in VBScript. Use IsType when necessary to test against specific subtypes. Not implemented in VBScript due to security considerations. Not implemented in VBScript. Like (Operators)

Deftype Option Base Option Compare Option Private Module Fixed-length strings Lset Rset

Not implemented in VBScriptall variables are of Variant type. Not implemented in VBScriptall arrays begin with a subscript of 0. Not implemented in VBScript. Use StrComp options as a workaround. Not supported. (No modules in VBScript) Not supported in VBScript. If absolutely required, use standard (variablelength) strings, and pad with spaces to desired length using Space(). Not supported in VBScript. Not supported in VBScript. Not supported in VBScript. Do not confuse the Mid statement with the Mid function. The function form of Mid is used to read characters within a string; the (currently unsupported) statement form is used to insert characters into a string. Not implemented in VBScriptLCase and UCase can be used to provide vbLowerCase and vbUpperCase functionality. Not implemented in VBScriptall variables are of Variant type.

Mid Statement

StrConv TypeName

As you can see from Table 13.2, there are quite a few VB features that are unimplemented in VBScript. The reasons are threefold: VBScript is designed to be a lightweight language for performance and resource reasons, it's necessary to prevent potential for damage via "dangerous" functions, and, the Web page platform has different characteristics than a VB program. The next section, "Style Differences," shows you how to accommodate yourself to the differences covered so far in this chapter.

Style Differences
Just as VB programming requires a change in philosophy from non-GUI programming, creating script-enabled Web pages hosted in a WWW browser mandates a new way of thinking and coding. To further complicate matters, the Internet is undergoing a series of concurrentand major transformations. If change indeed brings opportunity, the Internet is likewise what might be termed a "target-rich environment." It has lots of potential, and it has lots of risk. Surfing the Web is more accurate an aphorism than it might seem; the trick is to stay on top of the wave.

If you come from a traditional HTML programming background, your head is probably spinning about now. It'll pass. The Web will remain content-heavy, but the fantastic array of ActiveX controls, combined with HTML Layout Page functionality will provide the ability to do more than ever before, and to do it easier than you ever imagined. You'll have to learn to think in new ways, and at first, you'll need to resist the temptation to do things the old way. As long as the traditional HTML methods are more familiar to you than the new ActiveX features, you'll have to discipline yourself to work with the new capabilities, but it will be worth it in the long run, and besides, it won't take that long. VB programmers, on the other hand, will probably feel like they're back in the training-wheel stage. To an extent, it's an accurate perception: VBS is rather limited when compared to VB 4.0. But, unlike traditional VB programming, where the program is the totality of your efforts, or even VBA development, where you have freedom from language and security restrictions, VBScript applications are documents, and the code itself takes a role subservient to the end product.The changes of style affect you, as a developer, and, they affect the people who use what you write. Whether you're creating Internet pages, used by anyone who stumbles onto your site, or vertical-market intranet systems, you'll have to conform yourself to the realities and requirements of the medium, and the needs and expectations of the users.The following sections focus on the issues you'll need to keep in mind when working with VBScript.

Development Environment
The ActiveX Control Pad (covered in detail in Chapters 3-5) provides an excellent platform for creating script-enabled Web pages. However, convenient and powerful as it may be, it is not a fullfeatured IDE. In addition to the features that are available in VB, but are not present in the Control Pad, you'll have to deal with the "look and feel" differences, and limitations imposed by the target platform. Error Control The area that is perhaps most notable in its absence is any type of debugging facility. Because scripts are only one part of a page, it may be some time before there's much debugging capability built-in to VBS development tools. (When you reflect on the complexity of the Internet Explorer, and consider that any debugger worth its salt would have to emulate the IE, in addition to being able to interpret VBScript with the level of detail offered by VBbreakpoints, single-step, expression watches, etc. it becomes apparent that the undertaking would bemonumental.) This being acknowledged, you do still have to deal with debugging issues, and the onus is entirely on you at this stage of the game. What to do? First and foremost, read Appendix C, "VBScript Coding Conventions," and take its message to heart. By rigorously adhering to a set of standards, your code will be readable and understandable, and as a result, you'llbe better prepared to comprehend it later on. Use Option Explicit to help prevent errors caused by typos. Yes, even with Option Explicit turned on,

you won't find undeclared variables until you're running your page in the Internet Explorer, but at least you will find them. Layout Management When you're first learning VBScript, you'll probably experiment with Notepad, or an equivalent ASCII text editor. It's a fast, easy way to enter a few lines of code and save them to a file. However, once you begin to gain an understanding of ActiveX "stuff" (of which VBScript is but one part), you'll need to make the transition to the ActiveX Control Pad. While it's true that anything the Control Pad can do interactively, you can do manually in Notepad, it's also true that you can walk from New York to California. This is especially important to remember if you're really good in HTML, because you will have to consciously depart from familiar territory to something completely new and alien. It's likely that HTML as we know it is dead. It may not know it's dead, and maybe a lot of HTMLoriented folks don't know it's dead either. But, that doesn't change the reality that the new Layout Page flexibility has been needed for some time, and is finally available. HTML will remain as the underlying container, but the old-style flow-of-text formatting is gone, gone, gone, once ActiveX takes hold. Why is this such a big deal? Consider for a moment the confusion that surrounds HTML. The proliferation of new, proprietary formatting codeseverything from special font handling commands to table codes (and everything in between) exists to provide a measure of control over the appearance of the final product. The fact that it's possible at all, given the underlying formatting model, is a testament to the ability of the people writing browser software. But, it's resulted in language-bloat of gargantuan proportion. It's hard to believe that anyone is proficient in the near-countless codes, let alone the variations between one browser and another. The "big deal" is this: HTML Layout Pages provide a simple, elegant, and workable solution to the problems of placing, sizing, and formatting content and active elements in a web page. They sweep away the need for the vast majority of HTML arcana, and render much of it functionally obsolete. If it was a movie, it would be called, "Buggy-whip manufacturers vs. the Model T Redux." The moral is, don't be so attached to the old way of doing things that you miss out on the opportunity that the new technology presents. It can become a personal issue, especially if you are proficient in the existing system, but don't make the same mistake that so many have before during times of change. Remember the countless programmers who stayed with CP/M, because they thought, "MSDOS will never make it," or, the ones who stayed too long at the C: prompt, because "Windows? Who needs it!". It's good to learn from your mistakes. It's better to learn from the mistakes of others. Remember: the

trick is to stay on top of the wave.

User Environment
When desktop publishing software first became widely available, there was a wave of what were snickeringly referred to as "Ransom Notes"documents with numerous typefaces and sizes all on one sheet. People went wild playing with fonts, pitches, attributes, and formatting. Everyone became an instant typesetter. People who should have been managing operations instead spent their time playing at "publishing," and simple memos turned into major productions, replete with grammatical and spelling errors galore. Marshall McCluhan said, "The medium is the message." The sad fact is, people naturally tend to get wrapped up in the glitz and trappings of something new, especially when that something is a graphical presentation system. While this book can't cover everything you'll ever need to know about style, layout, and presentation, it can at least give you some pointers, and aim you in the right direction. The first bit of advice is simple. Simple, as in "Keep It Simple." Resist the temptation to do everything, everywhere, every time. You don't really have to use every last feature offered by ActiveX and VBS in each project you create. To be sure, the temptation will be therewhen it's easy to drop a group of controls into a tabbed container, and surround it with buttons and pictures and... You get the idea. Present the users with what needs to be presented, in a visually attractive manner, without overwhelming them. Sensory overload is not a pretty sight. One of the best sources of design insight is available to you immediately. Take a look at the different types of web pages that are posted on thenet. As of late, Microsoft seems to be paying particular attention to design issues, and, they seem to be doing a good job of it. Their pages are logical, relatively fast loading, and contain quite a bit of content without appearing "busy" or confusing. Other sites go to the other extreme. You've probably landed at one time or another on a page that took fifteen minutes to load, and consisted of miles of links and random bitmaps all arranged in an incredibly long single column down one drawn-out page. Some general, and near universal rules are easy to follow: avoid clutterdon't cram large numbers of controls on one page. If it's really necessary to have a lot of controls, use a tabbed container, and place the controls on tabs according to logical considerations. Try to put yourself in the place of the users. Remember that having thought up, written, debugged, and tested your project, you are intimately familiar with it in its entirety, but, a user dealing with it for the first time will find it all new, and no matter how well-designed it is, a bit intimidating. The fallacy in our field is the notion that as software becomes increasingly powerful, it becomes increasingly difficult to use. The best illustration of the falsehood of this statement is the new change that is taking over Web programming. It's changing from something of finite capability and incredible complexity, to something of limitless potential, and less and less effort.

From Here...
For all the similarities between VB and VBScript, it is truly a major new approach to programming. The following resources will prove very valuable.
q q q

See Chapters 3-5 for information on using the ActiveX Control Pad. See Chapters 15-20 for details on the VBScript language implementation. See Appendix C, "VBScript Coding Conventions," for hints on making your code maintainable by imposing consistent structure. See Que's Special Edition, Using VB 4, and Visual Basic 4 Expert Solutions, for extensive information on the Visual Basic language. Refer to the Microsoft Visual Basic Scripting Edition Language Reference, for exhaustive syntax descriptions and requirements of all statements, functions, and methods.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 14 - Comparing Scripting Languages


by Tom Tessier

q q

q q

q q

q q

q q

How JavaScript variables and operators work JavaScript operators and variable data type literals are very similar to their VBScript counterparts, both in usage and in declaration. How JavaScript execution flow works JavaScript execution flow and function calling is easily understood when compared to the corresponding VBScript equivalents. How to use JavaScript objects Learn how to use the built-in JavaScript objects and how to create your own objects. Examine which VBScript functions equate to the given JavaScript methods. How JavaScript event programming is used Thanks to the onEvent HTML definition, JavaScript event programming is identical to VBScript event programming. Real world example Examine a real world example of JavaScript in action, and then view the same page done in VBScript.

In this chapter, you learn about Microsofts implementation of the JavaScript language. It should be noted that JavaScript is not Java. While Java is a scaleable platform independent language requiring a Java compiler, JavaScript is a scripting language interpreted on-the-fly by a Web browser in much the same manner as VBScript. Developed by Netscape Communications Corporation, JavaScript (known as LiveScript during development) requires no compiler or development kits. In an attempt at compatibility with Netscapes browser, Microsoft has included a JavaScript interpreter within Internet Explorer 3.0.

JavaScript is not Java. Although JavaScript has syntax and operators exactly the same as that of Java, the concept and capabilities of JavaScript are very different. A Web browser interprets JavaScript on-the-fly upon contact with a page containing the

<SCRIPT LANGUAGE=JavaScript> tag, whereas Java is first precompiled using the Java SDK and then the resulting bytecodes are placed on a Web server and referenced on a page via the <APP> HTML command. When a browser encounters this tag, it loads in the precompiled bytecodes and interprets these on-the-fly. In essence, Java is half a compiled language and half an interpreted language, whereas JavaScript is entirely interpreted. Both JavaScript and Java resemble C++, without C+ +s nuisances such as memory leaks. Java is a distributed language, of considerably more power than JavaScript or even VBScript. Java is comparable to Visual Basic for Applications (OLE creator for use on Web pages) in power.

ON THE WEB http://java.sun.com If you are interested in Java programming, download the latest free Java SDK from this site.

An Overview of JavaScript
If youve done any Java or C++ programming, youll be at home with JavaScript. Unlike C++, it is not necessary to include a ; symbol at the end of each code line, but for consistency with Java it is recommended. The C++ comments // comment text and /* comment text */ also pass over to JavaScript. To wrap a section of code down to the next line in JavaScript, use the backslash (\) character. Refer to Table 14.1 for a summary of these very basic JavaScript syntax commands and their VBScript counterparts. As with VBScript, a JavaScript session is initiated via the <SCRIPT> command. However, instead of VBS the Language parameter is set to either LiveScript or JavaScript (LiveScript was the previous name of JavaScript). The following JavaScript code demonstrates how to use the <SCRIPT> tag: <SCRIPT Language=JavaScript> { JavaScript code body here } </SCRIPT> It should be noted that both JavaScript and VBScript are case sensitive. This means that the case of letters composing a name or object is importanta variable named Myvar is entirely different than

one written as myvar.

JavaScript Variables and Operators


As you probably know by now, some of the most basic instructions of any programming language are variable declarations and operators. These are used to set up numbers and text strings as well as to perform actions and comparisons which determine the outcome of a given program. Variables Variables are used to set up numbers and text strings for use later in a program. Variables in JavaScript are assigned exactly the same way as in VBScript. The variable name is on the left, and the corresponding data type literal is on the right. For example, to define an integer, a floating-point literal, a string, and a Boolean, one would write the following JavaScript program: myint = 10; mystring = Joe Moe; myfloat = 50.99; myboolean = false; The var command must be employed if you want to reuse a variable name inside of a function. For example, this JavaScript code changes the original value of the variable life to 299: function lifetime() { life = 100; changelife(); // call the changelife function document.write (life+ ); // write the life variable to the page } function changelife() { life = 299; // change life variable to 299

// (changes the original variable) document.write (life); // write the life variable } The page output is 299 299 (document.write is a built-in object which places text directly onto the HTML pagesee the "JavaScript Objects" section for more information). Now, lets look at the same JavaScript example, this time using var to create a new instance of the life variable: function lifetime() { life = 100; changelife(); // call the changelife function document.write (life+ ); // write the life variable to the page.. will // be unchanged } function changelife() { var life = 299; // create a new instance of the life variable // and initialize it to 299 document.write (life); // write this new life variable } The page output is 299 100. By using var, life is redeclared, hiding the previous definition in the code body. When the changelife function ends, the second life variable is destroyed and the original restored. Variable and function names must begin with a letter or underscore character. The remaining characters can include digits (09) and upper- or lowercase letters. Remember, the case of such variable names is important (in both VBScript and JavaScript)a function named MyFunction99 is entirely different from one called myfuncTion99 (see "JavaScript Execution Flow and Functions" for

more information on functions). The available JavaScript data type literals available for equating to variable names are as follows:
q q

Boolean literals: These literals represent a boolean type having a value of true or false only. Integer literals: These include all integer values such as 2, 1000, 999, and 20000, and may be written in JavaScript using decimal base 10 (default), octal base 8 (precede the digits with a 0), or hexadecimal base 16 (precede the digits/letters with a 0X). Floating-point literals: These represent all values that require a decimal point or exponent. For example, 10.4234435, 4e-16, and 2.35434e23 are all floating-point literals. string literals: These refer to any characters enclosed in quotation marks ( or ). For example, Hi peoples! and Good day mates are string literals. By using special JavaScript control characters inside of these strings, special effects can be achieved\n causes a new line; \t represents a tab; \\ indicates a backslash; \ causes a single quotation mark; and \ implements a double quotation mark.

When declaring a variable, note that its literal type is automatically determined at runtime by the browser. For example, n = 100 declares a variable of type integer. If, later on, n is assigned a floatingpoint literal, the browser automatically converts n to a floating-point variable. Operators Operators are used to perform actions and comparisons which determine the outcome of a given program section. For example, to add two numbers together, the JavaScript plus (+) operator is used: a = b + c; a is assigned the value of b plus c. To check if b is greater than c, one of the JavaScript compare (<, <=, >, or >=) operators must be used: if ( b > c ) If b is greater than c, then the code contained in the if statement will activate (see "JavaScript Execution Flow and Functions" for more information on if statements). Table 14.2 lists the various JavaScript operators and their corresponding VBScript counterparts. Table 14.2 Comparison of JavaScript and VBScript Operators Operation JavaScript Operator VBScript Operator Mathematical Operators Addition + +

Subtraction Multiplication Division Exponentiation Modulus Negation String concatenation Left shift Right shift Bitwise AND Bitwise OR Bitwise XOR Bitwise complement

* / N/A % + << >> & | ^ ~ Comparison Operators

* / \ ^ MOD + or & N/A N/A AND OR XOR NOT

Divide and return an integer value N/A

Less than Greater than Less than or equal to Greater than or equal to Equal to Not equal to Evaluation AND Evaluation OR Evaluation XOR

< > <= >= == != && || N/A

< > <= >= = <> AND OR XOR

All of the preceding operators function exactly the same as their VBScript counterparts. For example, take a look at this JavaScript code: a = b + c; a = b & c; The VBScript equivalent has the exact same structure: a=b+c

a = b AND c; For examples of JavaScript vs VBScript comparison operators, see the following section, or refer to Chapter 16, VBScript Operators.

JavaScript Execution Flow and Functions


JavaScripts methods for directing execution flow, via decision and loop statements, are identical to those of C/C++. Decision Statements These control statements evaluate an expression, and then take an action based on whether the expression is true or false. The if command executes one or more lines of code based on whether the expression in parentheses after the if statement is true. Note that expression makes use of the compare operators listed in the previous section, "JavaScript Operators." The following JavaScript program illustrates a typical if statement in action: if ( (str == ) && (myval < min) || (myval > max) ) alert(Str is empty, and either myval is less+ than min or greater than max); The JavaScript alert is only executed if the entire expression from left to right evaluates to true. In other words, the variable string str must be empty, and either myval less than min or myval greater than max for the expression to evaluate as true. Notice the use of the plus (+) operator to wrap the string over multiple lines. In VBScript, no parentheses enclose the if expression(s). As well, the Then command must be placed at the end of the if line. Finally, an end if is placed at the end of the entire if structure (after the executable code). The following presents exactly how the if statement is used in VBScript: if str = AND myval < min OR myval > max Then alert Str is empty, and either myval is less+ than min or greater than max end if

More than one line can be included for execution after the if statement by enclosing the line in standard C/C++ brackets. The following JavaScript code illustrates this: if (confirm(Proceed?)) { myval = min; myval++; } If the results of the built-in JavaScript function confirm (which initiates a YES/NO dialog box) are true (YES selected), then the two lines enclosed in { } are executed. In VBScript, the brackets must not be used since the interpreter keeps reading in lines of code until an end if statement is encountered. The else and else if commands are placed directly after if statements to select alternate code that executes when the if expression fails. else executes its alternate code every time, whereas the code contained in an else if statement only runs if its expression is true. For example, suppose one needed to perform three different actions, with only one action occurring at any given time based upon the value of certain variables. An if statement would be used to decide whether to perform the first action, an else if command to decide the second, and another else if statement (or simply else if this alternate code is to execute every time) for the third. The following JavaScript code illustrates the if... else concept: if (aint < bint) aint = bint; else if (aint > bint) { aint = cint; cint--; } else aint++;

In the preceding example, aint is set to bint only when aint is less than bint, otherwise aint is set to cint if aint is greater than bint. If neither the (aint < bint) or (aint > bint) expressions are true, then aint is incremented. VBScript if...else coding conventions follow exactly the same structure as in JavaScript. The only difference is that VBScript uses elseif to represent JavaScripts else if, and no { } brackets are used (an end if is simply placed at the end of the entire structure in VBScript). The following VBScript code is equivalent to the preceding JavaScript program: if aint < bint Then aint = bint elseif aint > bint Then aint = cint cint = cint - 1; else aint = aint + 1 end if It should be noted that it is possible to nest if...else statements within other if...else statements, as in the following JavaScript code snippet: if (aint < bint) { if (aint < cint) { aint = cint; cint++; } else aint = bint;

} The preceding example in VBScript follows: if aint < bint Then if aint < cint Then aint = cint cint = cint + 1 else aint = bint end if end if Loop Statements Loop statements repeat an action over and over again until an expression evaluates to true or false. The while loop executes a set of commands as long as the test expression in parentheses after the while statement evaluates to true. As in JavaScripts if...else structure, { } brackets must enclose the repeatable code body of the while statement. The { } brackets are optional if the code body is composed of only one line. The below JavaScript program shows the while loop in action: while ( aint < cint || aint < bint ) { aint++; bint--; } The preceding program executes the two lines over and over until aint = cint or aint = bint. Literally, while aint is less than cint or aint is less than bint, increment aint and decrement bint. What follows is the VBScript version of the above program:

while aint < cint OR aint < bint aint = aint + 1 bint = bint - 1 wend Note that for the while loop in VBScript, parenthesis are not needed around the conditional expression, no { } are used around the code body, and a wend statement terminates the repeatable code segment. The for loops structure is very similar to that of the while loop. Observe the for loop in the following JavaScript code: for (var i = 0; i < 10; i++) { aint++; bint=bint+10; } The for loop is decomposed as follows: for (expression a; expression b; expression c) Expression a is executed when the for loop begins. This is usually where one initializes the loop variables. While Expression b is true, the statements enclosed in the { } area execute. Upon reaching the last statement enclosed within the { } block, expression c runs and the loop repeats until expression b becomes true, upon which the loop ends. The equivalent VBScript code for the preceding for loop is listed below: for i = 0 to 10 step 1 aint = aint + 1 bint = bint + 10 next Again, no parentheses enclose the expression list in VBScript. As well, a next statement is used to

indicate the end of the repeatable code body, in place of JavaScripts { } commands. Observe that the step 1 VBScript keyword is optional in this case, since the step size (amount to increment i by) automatically defaults to one. Refer to Chapter 17, VBScript Control of Flow and Error Handling, for a complete explanation of VBScripts flow control handling. Functions A function is a means of subdividing a program into smaller, easier to read code packets. Functions are also modular, in that they can be reused with ease from program to program. A function is usually passed a list of variables, performs actions based upon these variables, and then returns a value to the calling code. The calling code then performs subsequent actions based upon this returned value. JavaScript functions are defined using the function keyword, as follows: function name(arguments) { code body of function } Name indicates the name of the function to use, while arguments represent the values or variables passed to the function for use in its code body. The return statement is used in the functions code body to pass a value back to the calling code. The preceding function is called with the below JavaScript: name(arguments); Or, if the function is returning a needed value via the return statement, the function must be called with the equate (=) operator to assign the returned value to a variable. The below JavaScript code illustrates this: function name(arguments) { code body of function return value; } storevalue = name(arguments);

The variable storevalue is assigned the value returned by the name function. VBScript, in contrast, defines functions using sub. Refer to the VBScript function layout shown below: sub name(arguments) code body of function end sub Notice the differences between JavaScript and VBScript. First of all, VBScript employs sub in place of JavaScripts function. Secondly, VBScript uses end sub to terminate the function code body, instead of JavaScripts enclosing { } brackets. If function and end function are used in place of sub and end sub, the VBScript function is allowed to return a value. The below VBScript code illustrates how this is done: function name(arguments) code body of function return name end sub Notice that in VBScript, the actual name of the function must be used after the return statement. VBScript functions are called almost exactly the same way as in JavaScript. Refer to the below VBScript example: name arguments Notice that no parenthesis are used in the VBScript version of the function call. As in JavaScript, if the VBScript function is returning a value, the function must be called with the equate (=) operator to assign the returned value to a variable. The below VBScript shows this: storevalue = name arguments The variable storevalue is assigned the value returned by the name function (note that name must be declared using VBScripts function and end function statements in order to return a value). See Chapter 19, VBScript Procedures, for more information on VBScript subroutines and functions.

All functions should be placed between <HEAD><SCRIPT> and </SCRIPT></HEAD> tags, since the <HEAD> tag information is loaded first on a Web page. This ensures that no JavaScript or VBScript code attempts to call a function that has not been loaded yet. Listing 14.1 and the resulting page shown in Figure 14.1 demonstrate JavaScript control flow and function calling in action. Listing 14.2 is the same program in VBScript. Listing 14.1 can be found on the CD-ROM in file LST18_1.HTM.

Listing 14.1 LST18_1.HTMSample JavaScript Program Illustrating Control Flow and Function Calling <SCRIPT Language="JavaScript"> function writepage(start_text, number_repetitions) { document.write ("<H1>"+start_text+"</H1><BR>"); for (j = 0; j < number_repetitions; j=j+2) // increment j by 2 each // time through the loop { document.write ("J = "+j+"<BR>"); // write the value of j // to the page if (j == 10) document.write ("<H2>Five times through</H2><BR>"); else if (j == 20) document.write ("<H3>Ten times through</H3><BR>"); } } // end of function writepage // above function has not been executed up to this point... writepage ("Greetings OB1. We meet again at last.",20); // call the writepage function with "Greetings... for the first argument // and 20 for the second argument </SCRIPT> FIG. 14.1 The resulting page generated both by the JavaScript in Listing 14.1 and the VBScript in Listing 14.2. Listing 14.2 can be found on the CD-ROM in file LST18_2.HTM.

Listing 14.2 LST18_2.HTMVBScript Equivalent of Listing 14.1 <SCRIPT Language="VBS"> sub writepage(start_text, number_repetitions) document.write "<H1>" & start_text & "</H1><BR>" for j = 0 to 18 step 2 ' increment j by two each ' time through the loop document.write "J = " & j & "<BR>" ' write the value of J ' to the page if j = 10 then document.write "<H2>Five times through</H2><BR>" elseif j = 20 then document.write "<H3>Ten times through</H3><BR>" end if next end sub ' end of function writepage ' above function has not been executed up to this point... writepage "Greetings OB1. We meet again at last.",20 ' call the writepage function with "Greetings... for the first ' argument and 20 for the second argument </SCRIPT>

JavaScript Objects
JavaScript does not provide all of the features of a true Object Oriented Programming (OOP) language. Features such as encapsulation, inheritance, and abstraction are missing. It does in fact allow one to create and use objects that have methods (functions associated with an object) and properties (variables or attributes of an object). JavaScript has several built-in objects available for use. Some of these objects are quite similar to VBScripts built-in functions. Built-In Objects VBScript has functions, whereas JavaScript has objects. These objects in turn have methods (functions associated with the object) and properties (variables associated with the object). These JavaScript built-in objects are used very differently than the VBScript built-in functions. First of all, a property is an attribute or variable of an object while a method is a function associated with the object. In JavaScript, for example, one would use the following code to get the length of a string: mystring = Greetings;

stringlength = mystring.length; stringlength2 = Greetings.length; where stringlength contains the same value as stringlength2. Notice that the string itself is treated as an object and the length is simply a property of this object. Observe that a period separates the object name on the left from the desired property on the right. The JavaScript convention, borrowed from C/ C++ (which Java also uses), is to have the object name on the left, with the desired method (function) or property (variable) on the right (a dot separates the object on the left from the method or property on the right). To perform similar actions in VBScript, built-in functions must be used. For example, to mimic the earlier JavaScript code that computed the length of a string, the VBScript len function must be employed as in the below VBScript program sample: mystring = Greetings stringlength = len(mystring) stringlength2 = len(Greetings) Notice that built-in VBScript functions must have parenthesis surrounding their arguments (as in len (mystring)). In order to obtain a deeper understanding of the JavaScript objects in Table 14.5, each of them will now be examined in greater detail.
String Object

To access the string object, a string variable or literal must be used as the object name on the left, with the desired string object method (function) or property (variable) on the right (left and right separated by a dot again). For example, observe the toUpperCase() method in the below JavaScript: newstring = oldstring.toUpperCase(); newstring is filled with the contents of oldstring (oldstrings contents are converted to uppercase first). The VBScript equivalent of the preceding line follows: newstring = ucase(oldstring) Properties are accessed the same way, as illustrated by the JavaScript string object example just after Table 14.5.
Math Object

In order to use any of the math properties and methods, the Math keyword (note the capital M) must precede all references to the math object. Refer to the following JavaScript code: a = Math.cos (Math.PI/4); b = Math.pow(3,5); When run, the above program gives a = 0.70710678 and b = 243. Alternatively, the special JavaScript keyword with can be used to associate ALL references to a method or property to a given object. For example, using with on the Math object in the previous code gives the following new JavaScript: with (Math) { a = cos (PI/4); b = pow (3,5); } The VBScript version of the preceding code follows: a = cos (3.14159/4) b = 3^5 Note again that VBScript uses functions in place of JavaScripts objects (the cos function, and the ^ function).
Window Object

The window object represents all properties and methods associated with the browser itself. This object allows access to the status bar, activates pop-up message windows, and so forth. It is not necessary to prefix any of the window objects properties and methods with the window keyword. For example, look at the following JavaScript code: window.alert (INTRUDER ALERT! INTRUDER ALERT!); Instead of accessing the alert method (function) via window.alert, JavaScript allows alert alone to be used (since alert is a method of the window object). The below JavaScript code performs exactly the same function as in the previous example:

alert (INTRUDER ALERT! INTRUDER ALERT!); The VBScript equivalent follows: alert INTRUDER ALERT! INTRUDER ALERT! The window keyword may also optionally be placed in front of the VBScript alert function, since the web browsers interpreter automatically removes any window. statements on-the-fly while going through the web page.
Location Object

The location object represents only the properties associated with the current document location/URL (http://www.solstar.com is an example of a URL, or Uniform Resource Locator). Having no methods, the location object is used to access and/or change the current page (URL) the document is pointing to. The JavaScript location objects properties must be prefixed with the location keyword. Refer to the following JavaScript code: location.href = http://www.url.com; The preceding example points the current page to http://www.url.com (in other words, the current page is lost, and the new page replaces it). Pointing the location.href to itself (location.href = location. href) causes the document to reloadhowever, this only works in Netscape 2.0 and up (although the final release of Internet Explorer 3.0 may in fact support dynamic document reloads like Netscape 2.0). Notice from Table 14.5 that the VBScript equivalent of the JavaScript location.href object is exactly the same. The VBScript location.href is not actually an object, however. Instead, think of it as a global variable, built-into the VBScript language. So the VBScript version of the preceding JavaScript code is exactly the same, as illustrated below: location.href = http://www.url.com
Document Object

The document object represents all of the properties and methods associated with the actual HTML document itself. This object allows write access to the page, lets HTML form input areas be examined and/or changed, and so on. The properties and methods of the document object must be prefixed with the document keyword. For example, to write directly to the HTML page, use the write method (function) as illustrated by the following JavaScript: document.write (Well good day to you too!!); Note that one cannot use document.write AFTER the page has completely loaded and executed (ie: in an event, for examplesee the following JavaScript Event Programming section).

The VBScript function equivalent operates almost exactly the same way, as shown here: document.write Well good day to you too!! document.write is not an object in VBScript - think of it as a built-in function. Notice that this document.write function is called using standard VBScript function calling practices: no parenthesis must enclose the arguments. When the web browser encounters a form defined in standard HTML code via the <FORM> tag, an array table is set up for use by JavaScript or VBScript. For each pair of <FORM> and </FORM> tags, a separate entry in the document.forms array object is created. To access individually named <INPUT> tags in these forms, append the desired <INPUT> items name and VALUE attribute to the document.forms object, as in the JavaScript in Listing 14.3. The output of Listing 14.3 is shown in Figure 14.2. Listing 18.3 can be found on the CD-ROM in file LST18_3.HTM.

Listing 14.3 LST18_3.HTMJavaScript Program Illustrating document.forms[0] Array Object to Access Form Data <HTML><BODY> <FORM> <INPUT TYPE="text" NAME="accessme"> </FORM> </BODY></HTML> <SCRIPT Language="JavaScript"> document.forms[0].accessme.value = "HIYA MON!"; </SCRIPT> FIG. 14.2 The resulting page generated by the JavaScript in Listing 14.3. The document.forms[0] array is indexing the first form in the document (form 0). As well, the object is reading the accessme form input and changing its value to the string HIYA MON! Notice the code that changes the form input must be placed after the definition of the accessme input, since the page is loaded into the browser from the top down. If the JavaScript document.forms[0].accessme. value code is placed above the actual form, no data can be entered into the form input: the <FORM> tag has not even been read in and defined at that point. Forms can also be referenced by name instead of by array, as in the JavaScript in Listing 14.4. Listing 14.4 can be found on the CD-ROM in file LST18_4.HTM.

Listing 14.4 LST18_4.HTMJavaScript Program Demonstrating Form Data Access via Form Names <HTML><BODY> <FORM NAME=form_name> <INPUT TYPE="text" NAME="accessme"> </FORM> </BODY></HTML> <SCRIPT Language="JavaScript"> document.form_name.accessme.value = "HIYA MON!"; </SCRIPT> The JavaScript in Listing 14.5 shows that Microsofts Internet Explorer 3.0 Alpha 1 (4.70.1028) allows one to get away with not using a <FORM> tag in the JavaScript. Listing 14.5 can be found on the CD-ROM in file LST18_5.HTM.

Listing 14.5 LST18_5.HTMJavaScript Program Showing Internet Explorer 3.0s Capability to Create and Access Form Data without the Need of <FORM> Tags <HTML><BODY> <INPUT TYPE="text" NAME="accessme"> </BODY></HTML> <SCRIPT Language="JavaScript"> accessme.value = "HIYA MON!"; </SCRIPT> The preceding JavaScript code is incompatible with the Netscape browser. The Netscape client requires that all input elements be placed within <FORM> and </FORM> tags. As long as you can get used to treating form inputs as page outputs, the concept of the form object can be easily understood. Unlike the JavaScript in Listing 14.3, the forms[index] array property cannot be used to access VBScript form data. Instead, the actual form name must be used, as in the VBScript in Listing 14.6. Listing 14.6 can be found on the CD-ROM in file LST18_6.HTM.

Listing 14.6 LST18_6.HTMVBScript Program Illustrating Form Access via Form Names

<HTML><BODY> <FORM NAME=form_name> <INPUT TYPE="text" NAME="accessme"> </FORM> </BODY></HTML> <SCRIPT Language="VBS"> document.form_name.accessme.value = "HIYA MON!" </SCRIPT> For VBScript in Internet Explorer 3.0 Alpha 1 (4.70.1028), the <FORM> tag is not even necessary, as shown in the VBScript in Listing 14.7. Listing 14.7 can be found on the CD-ROM in file LST18_7. HTM.

Listing 14.7 LST18_7.HTMVBScript Program Demonstrating Internet Explorer 3.0s Capability to Create and Access Form Data without the Need of <FORM> Tags <HTML><BODY> <INPUT TYPE="text" NAME="accessme"> </BODY></HTML> <SCRIPT Language="VBS"> accessme.value = "HIYA MON!" </SCRIPT> In general, it is good practice to use the <FORM> tag around <INPUT> sections. That way the contents of the form can be submitted to a server for post processing, and converting the HTML/ VBScript code to Netscapes JavaScript implementation becomes trivial. Creating Objects In JavaScript, use the C++ new command to dynamically create an object. Unlike C++ (and like Java), these dynamically created objects do not need to be destroyed, as the interpreter does all construction and destruction on-the-fly. Although VBScript can assign an object reference to a variable or property (as in Set formvar = document.form_name), it cant actually create a new object as JavaScript does. To create an object, first define a function for the new object, as illustrated by the following JavaScript code: function myobject(arguments)

{ methods/properties of function } Then later in the program, use the new command to dynamically create a new instance of the object. The next JavaScript illustrates this: newobject = new myobject(arguments);
Creating Properties and Methods for Objects

When in an object function, use the keyword this to refer to the current object. With this, object properties are easily created, as the following JavaScript shows: function myobject(name, number) { this.name = name; this.number = number; } An instance of the object must be created with new, as the following JavaScript demonstrates: newobject = new myobject(Morphing Fork,22) The properties of this new object can then be accessed in the usual way (object on the left, period, property or method on the right). For example, to assign values to two variables named a and b, use the following JavaScript: a = newobject.name; b = newobject.number; Where a = Morphing Fork and b = 22 (these values were defined when newobject was created via the new command, shown earlier). To add a method to this object, simply point a property in the object definition to a function, as the this JavaScript code illustrates: function myobject(name, number)

{ this.name = name; this.number = number; this.method_name = method_name; } function method_name() { code body of method } The methods of this new object are again accessed in the usual wayobject on the left, period, method (function) on the right.
Creating an Array Object

As an example of object creation, the following creates an array object for use in your JavaScript: function CreateArray(num) { this.length = n; for (var i = 1; i <= n; i++) { this[i] = 0; } return this }

This creates an array of num entries with a length property indicating the number of entries in the array. The array entries are initialized to zero upon creation. To make an array, use the object in JavaScript as follows: array = new CreateArray(3); array[1] = 3; array[2] = 1; lenarray = array.length; Compared to JavaScript, making arrays in VBScript is easy. For example, the below VBScript uses the Dim statement in conjunction with Array to define an array: Dim A A = Array(3,1,2) B = A(2) lenarray = len(A)

JavaScript Event Programming


As in VBScript, JavaScript can be activated by events placed in ordinary HTML tags such as <INPUT> and <FORM>. These event tags work exactly the same as in VBScript, since JavaScript and VBScript share common HTML code. For example, what follows is the JavaScript HTML onChange handler to call a function when a form input named text_area changes: <INPUT TYPE=text NAME=text_area onChange=function(arguments)> In VBScript HTML, the function is called without parenthesis as shown in this next line of code: <INPUT TYPE=text NAME=text_area onChange=function arguments> It is also possible to place JavaScript code directly into the onEvent area, as shown in this line of code: <INPUT TYPE=text NAME=text_area onChange=alert(Don\t touch that dial!);> Notice the use of the apostrophe () character within the alert. This serves to prevent the interpreter from confusing the start of the alert text with the end of the onChange event (which must be enclosed in quotation marks). Also, a \ character is used to create the apostrophe for the dont text, since it

would be confused with a closing apostrophe otherwise. VBScript code can also be used in an onEvent, as the following example illustrates: <INPUT TYPE=text NAME=text_area onChange=alert Don\t touch that dial! > The browser automatically determines which language (VBScript or JavaScript) to use in onEvents, based upon what was previously implemented in the same file. Beware of mixing JavaScript and VBScript code within the one filethis crashes Internet Explorer 3.0 (when Explorer 3.0 encounters an onEvent containing a language different from what was used before in previous <SCRIPT> tags, a runtime error is generated). As of this writing, the current version of Internet Explorer 3.0 is Alpha 1 (4.70.1028). This version does not function properly with the onSelect, onMouseOver, and onSubmit event handlers. JavaScript code using these events under Netscape 2.0 or higher works just fine, however. Refer to Chapter 18, VBScript Event Programming, for more information on using events in VBScript.

Putting It All Together


Using all of the basic techniques learned so far, you now have the ability to create real world JavaScript applications. At the very least, you should be able to convert existing VBScript applications to JavaScript (to guarantee your web pages compatibility with Netscape 2.0 as well as Internet Explorer 3.0). The JavaScript found in Listing 14.8 and the VBScript equivalent in Listing 14.9 (both listings are too large to print entirely here, the full versions can be found on the CD) generate the page shown in Figure 14.3. The complete Listing 14.9 can be found on the CD-ROM in file LST18_9.HTM. This type of page is the perfect example of a typical real world JavaScript and VBScript Web page. The program makes use of HTML tables extensively to create an order form, and employs all of the concepts Ive discussed so far, as well as those mentioned throughout the rest of this book. Refer to Chapter 2, "Review of HTML," for more examples of table usage. The complete Listing 14.8 can be found on the CD-ROM in file LST18_8.HTM. ON THE WEB http://www.stars.com/Tutorial/HTML/Tables Check out this site for more examples of table usage. http://www.w3.org/pub/WWW/MarkUp/Tables/950915_tables.html This site contains the HTML 3.0 draft specification of the table model.

Listing 14.8 LST18_8.HTMReal World JavaScript Program: Calculates the Total Price Based on User Selections <HTML> <HEAD> <SCRIPT Language="JavaScript"> // below variables automatically globalized since they are not defined inside // any functions - ie: these variables will be remembered each time through // the updateprice function old_p_price=0; // initialize variables to 0 old_d_price=0; old_v_price=0; old_m_price=0; old_o_price=0; old_c_price=0; subtotal_price=0; function updateprice (who_called, chosen) { // processor price data p0 = 2000; // P166 p1 = 1800; // P150 p2 = 1500; // P133 p3 = 1300; // P120 p4 = 1100; // P100 p5 = 900; // P90 p6 = 600; // P75 p7 = 425; // P66 p8 = 300; // P60 . . . // point to subtotal form input form_subtotal = document.computer.subtotal; if (who_called == 0) // clicked on Processor area? { // point to processor price form input curItem = document.computer.processor_price; if (chosen == 0) // P166? { curItem.value = "$"+p0; new_prev_price = p0; } else if (chosen == 1) // P150? {

curItem.value = "$"+p1; new_prev_price = p1; } else if (chosen == 2) // P133? { curItem.value = "$"+p2; new_prev_price = p2; } else if (chosen == 3) // P120? { curItem.value = "$"+p3; new_prev_price = p3; } else if (chosen == 4) // P100? { curItem.value = "$"+p4; new_prev_price = p4; } else if (chosen == 5) // P90? { curItem.value = "$"+p5; new_prev_price = p5; } else if (chosen == 6) // P75? { curItem.value = "$"+p6; new_prev_price = p6; } else if (chosen == 7) // P66? { curItem.value = "$"+p7; new_prev_price = p7; } else if (chosen == 8) // P60? { curItem.value = "$"+p8; new_prev_price = p8; } // subtract the old processor price from the subtotal subtotal_price = subtotal_price - old_p_price; // and set the old processor price to the newly // selected processor price old_p_price = new_prev_price; // and add the new processor price to the subtotal subtotal_price = subtotal_price + new_prev_price; // and set the subtotal form input to the subtotal price

form_subtotal.value = "$"+subtotal_price; } . . . // compute the shipping value (0.1 * the subtotal_price) document.computer.shipping.value = "$"+(0.1 * subtotal_price); // and compute the total amount owed (the subtotal_price + the // shipping value) document.computer.total.value = "$"+ (subtotal_price + 0.1 * subtotal_price); } </SCRIPT> </HEAD> <BODY> <FORM NAME="computer"> <TABLE BORDER=1 BGCOLOR="#FFFFCC" WIDTH=80 ALIGN=LEFT> <FONT SIZE=2 COLOR=BLUE> <TR><TD BGCOLOR=WHITE ALIGN=CENTER>Processor...</TD></TR></ FONT> <TR><TD> <!-- when P166 is clicked on, call updateprice with arguments 0 and 0 --> <INPUT TYPE=RADIO NAME=processor onClick="updateprice(0,0)"> P166 </TD></TR> <TR><TD> <!-- when P150 is clicked, call updateprice with arguments 0 and 1 --> <INPUT TYPE=RADIO NAME=processor onClick="updateprice(0,1)"> P150 </TD></TR> <TR><TD> <INPUT TYPE=RADIO NAME=processor onClick="updateprice(0,2)"> P133 </TD></TR> <TR><TD> <INPUT TYPE=RADIO NAME=processor onClick="updateprice(0,3)"> P120 </TD></TR> <TR><TD> <INPUT TYPE=RADIO NAME=processor onClick="updateprice(0,4)"> P100 </TD></TR> <TR><TD> <INPUT TYPE=RADIO NAME=processor onClick="updateprice(0,5)">

P90 </TD></TR> <TR><TD> <INPUT TYPE=RADIO NAME=processor onClick="updateprice(0,6)"> P75 </TD></TR> <TR><TD> <INPUT TYPE=RADIO NAME=processor onClick="updateprice(0,7)"> P66 </TD></TR> <TR><TD> <INPUT TYPE=RADIO NAME=processor onClick="updateprice(0,8)"> P60 </TD></TR> <TR><TD> <INPUT TYPE=TEXT NAME=processor_price SIZE=11 VALUE="$0.00"> </TD></TR> </TABLE> . . . <BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR> <TABLE BORDER=1 BGCOLOR="#FFFFCC" WIDTH=530 HEIGHT=90 ALIGN=LEFT> <TR><TD> Subtotal </TD></TR> <TR><TD> Shipping Charges (please allow 4-6 weeks for delivery) </TD></TR> <TR><TD> Total </TD></TR> </TABLE> <!-- form inputs who's values are changed by the JavaScript code, depending on the selections the user has made in regards to processor type, monitor, memory, and so forth --> <TABLE BORDER=1 BGCOLOR="#FFFFCC" WIDTH=70> <TR><TD> <INPUT TYPE=TEXT NAME=subtotal SIZE=10 VALUE="$0.00"> </TD></TR> <TR><TD> <INPUT TYPE=TEXT NAME=shipping SIZE=10 VALUE="$0.00"> </TD></TR> <TR><TD>

<INPUT TYPE=TEXT NAME=total SIZE=10 VALUE="$0.00"> </TD></TR> </TABLE> <BR> <INPUT TYPE=SUBMIT VALUE="Order now"> <A HREF="index.html">Return to main page</A> </FORM> </BODY> </HTML> FIG. 14.3 The resulting computer pricing page generated both by the JavaScript in Listing 14.8 and the VBScript in Listing 14.9. The complete Listing 14.9 can be found on the CD-ROM in file LST18_9.HTM.

Listing 19.9 LST18_9.HTMVBScript Equivalent of Listing 14.8 <HTML> <HEAD> <SCRIPT Language="VBS"> ' use Dim to indicate that these variables are to be remember each time ' through the updateprice subroutine - ie: to GLOBALIZE the below variables Dim old_p_price ' old processor price (integer) Dim old_d_price ' old drive price (integer) Dim old_v_price ' old video price (integer) Dim old_m_price ' old memory price (integer) Dim old_o_price ' old os price (integer) Dim old_c_price ' old case price (integer) Dim subtotal_price ' subtotal price (integer) old_p_price=0 ' initialize variables to 0 old_d_price=0 old_v_price=0 old_m_price=0 old_o_price=0 old_c_price=0 subtotal_price=0 sub updateprice (who_called, chosen) Dim form_subtotal

Dim curItem ' processor price data p0 = 2000 ' P166 p1 = 1800 ' P150 p2 = 1500 ' P133 p3 = 1300 ' P120 p4 = 1100 ' P100 p5 = 900 ' P90 p6 = 600 ' P75 p7 = 425 ' P66 p8 = 300 ' P60 . . . ' point to subtotal form input Set form_subtotal = document.computer.subtotal if who_called = 0 Then ' clicked on Processor area? ' point to processor price form input Set curItem = document.computer.processor_price if chosen = 0 Then ' P166? curItem.value = "$" & p0 new_prev_price = p0 elseif chosen = 1 Then ' P150? curItem.value = "$" & p1 new_prev_price = p1 elseif chosen = 2 Then ' P133? curItem.value = "$" & p2 new_prev_price = p2 elseif chosen = 3 Then ' P120? curItem.value = "$" & p3 new_prev_price = p3 elseif chosen = 4 Then ' P100? curItem.value = "$" & p4 new_prev_price = p4 elseif chosen = 5 Then ' P90? curItem.value = "$" & p5 new_prev_price = p5 elseif chosen = 6 Then ' P75? curItem.value = "$" & p6 new_prev_price = p6 elseif chosen = 7 Then ' P66? curItem.value = "$" & p7 new_prev_price = p7 elseif chosen = 8 Then ' P60? curItem.value = "$" & p8 new_prev_price = p8

end if ' subtract the old processor price from the subtotal subtotal_price = subtotal_price - old_p_price ' and set the old processor price to the newly ' selected processor price old_p_price = new_prev_price ' and add the new processor price to the subtotal subtotal_price = subtotal_price + new_prev_price ' and set the subtotal form input to the subtotal price form_subtotal.value = "$" & subtotal_price . . . ' compute the shipping value (0.1 * the subtotal_price) document.computer.shipping.value = "$" & (0.1 * subtotal_price) ' and compute the total amount owed (the subtotal_price + the ' shipping value) document.computer.total.value = "$" & (subtotal_price + 0.1 * subtotal_price) end sub </SCRIPT> </HEAD> <BODY> <FORM NAME="computer"> <TABLE BORDER=1 BGCOLOR="#FFFFCC" WIDTH=80 ALIGN=LEFT> <FONT SIZE=2 COLOR=BLUE> <TR><TD BGCOLOR=WHITE ALIGN=CENTER>Processor...</TD></TR></ FONT> <TR><TD> <!-- when P166 is clicked on, call updateprice with arguments 0 and 0 --> <INPUT TYPE=RADIO NAME=processor onClick="updateprice 0,0"> P166 </TD></TR> <TR><TD> <!-- when P150 is clicked on, call updateprice with arguments 0 and 1 --> <INPUT TYPE=RADIO NAME=processor onClick="updateprice 0,1"> P150 </TD></TR> <TR><TD> <INPUT TYPE=RADIO NAME=processor onClick="updateprice 0,2"> P133 </TD></TR> <TR><TD> <INPUT TYPE=RADIO NAME=processor onClick="updateprice 0,3">

P120 </TD></TR> <TR><TD> <INPUT TYPE=RADIO NAME=processor onClick="updateprice 0,4"> P100 </TD></TR> <TR><TD> <INPUT TYPE=RADIO NAME=processor onClick="updateprice 0,5"> P90 </TD></TR> <TR><TD> <INPUT TYPE=RADIO NAME=processor onClick="updateprice 0,6"> P75 </TD></TR> <TR><TD> <INPUT TYPE=RADIO NAME=processor onClick="updateprice 0,7"> P66 </TD></TR> <TR><TD> <INPUT TYPE=RADIO NAME=processor onClick="updateprice 0,8"> P60 </TD></TR> <TR><TD> <INPUT TYPE=TEXT NAME=processor_price SIZE=11 VALUE="$0.00"> </TD></TR> </TABLE> . . . <BR><BR><BR><BR><BR><BR><BR><BR><BR><BR><BR> <TABLE BORDER=1 BGCOLOR="#FFFFCC" WIDTH=530 HEIGHT=90 ALIGN=LEFT> <TR><TD> Subtotal </TD></TR> <TR><TD> Shipping Charges (please allow 4-6 weeks for delivery) </TD></TR> <TR><TD> Total </TD></TR> </TABLE> <!-- form inputs who's values are changed by the VBScript code, depending on the selections the user has made in regards to processor type, monitor, memory, and so forth --> <TABLE BORDER=1 BGCOLOR="#FFFFCC" WIDTH=70> <TR><TD> <INPUT TYPE=TEXT NAME=subtotal SIZE=10 VALUE="$0.00"> </TD></TR> <TR><TD>

<INPUT TYPE=TEXT NAME=shipping SIZE=10 VALUE="$0.00"> </TD></TR> <TR><TD> <INPUT TYPE=TEXT NAME=total SIZE=10 VALUE="$0.00"> </TD></TR> </TABLE> <BR> <INPUT TYPE=SUBMIT VALUE="Order now"> <A HREF="index.html">Return to main page</A> </FORM> </BODY> </HTML>

From Here...
This concludes your crash course in JavaScript. Perhaps in a later release, Netscape will include VBScript support in its interpreter. Until then, if you want to create script pages compatible with both Netscape 2.0 and Internet Explorer 3.0, JavaScript is the way to go. VBScript is perhaps inherently more powerful with its capability to dynamically alter the behavior of Java and OLE objects (via the <OBJECT> tag), whereas Netscape 2.0 cannot yet read in a Microsoft OLE object (NetScape works great with Java, however). I wouldnt be surprised if Netscape Communications soon incorporated VBScript into its Netscape browser. So in the end, it probably doesnt really matter which scripting language you use: all browsers will be able to read all scripts. For more information on JavaScript and VBScript, go to the following sites and chapters. ON THE WEB http://home.netscape.com/eng/mozilla/Gold/handbook/javascript/index.html Refer to this site for NetScapes JavaScript Authoring Guide. http://www.c2.org/~andreww/javascript This site contains an index of various JavaScript pages on the web plus JavaScript source code.
q q

Chapter 15, VBScript Operators for a description of VBScript Operators. Refer to Chapter 16, VBScript Control of Flow and Error Handling, for a complete explanation of VBScripts flow control handling. See Chapter 19, VBScript Procedures, for more information on VBScript subroutines and functions. Refer to Chapter 17, VBScript Event Programming, for more information on using events in VBScript. Refer to Chapter 3 for more information on basic HTML and Tables.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 15 - VBScript Data Types and Variables


by Ibrahim Malluf

In this chapter
q q q q q q

Learn how Visual Basic Script manages your state data Introduction to the Visual Basic Variant data type as well as how data is scoped. Learn about the different data types that are provided There is a brief description of each data type along with examples of use where appropriate. Data Typing and Variable naming conventions How to minimize errors due to mismatched data types and ideas on writing maintainable VBScript code.

Visual Basic Script, in keeping with its lightweight implementation, has limited its data types to only onethe variant. For those unfamiliar with Visual Basic in general, the variant is a data type that can contain a representation of almost any other data type. Strings, longs, doubles, dates, and so on are easily contained within a variant. This is what is known as weak data typing and is the opposite of the preferred strong typing of a more robust programming environment like Visual Basic Professional, where you have specific data types to contain your data. Having a weakly-typed language offers the simplicity of the variant in use for the programmer in declaring variable storage and simplicity in Visual Basic Script's implementation since the code library for VBS need only contain the functionality of the variant type. On the other hand, this simplicity also caries the danger of passing the wrong data type to a procedure that can be very hard to debug. VBScript programs can become real monsters to maintain if the programmer doesn't take care to insure some sort of procedural level data typing. It's a tradeoff that seems to work quite well.

The Variant's Data Sub-Types


Let's take a more in-depth look at the variant's capabilities. As I mentioned, the variant can contain any of the other data types normally associated with Visual Basic. It also automatically converts between data types where possible. When assigning a value to a variant, Visual Basic fits that value into a type that it assumes is the optimal type. Whole numbers become integer types, numbers with

fractional portions become floating point types, and character values become string types without any intervention on your part. For example, if you have two variables, one containing a string and the other a numeric value, you can concatenate them without any explicit type conversions. The result here is that MyDisplay contains the string "The Number is: 1234.5678." In most cases, you do not have to be concerned with the conversions of one data type to another since all conversions are automatic. But you need to be careful in your use of the + operator. While it concatenates strings, if you use it to concatenate two numericals or two numeric strings, they are added instead of concatenated. Therefore, always use the & operator to concatenate string type variants and the + operator to add numeric values. The following listing shows the proper method to use when concatenating a string. MyString = "The Number is: " MyAnswer = 1234.5678 MyDisplay = MyString & MyAnswer

The Boolean Sub-Type


The Boolean sub-type is a 16-bit signed integer, but when accessed can only return a True (1) or False (0). In Visual Basic Script you can use either the keywords or the numeric representation of True and False. If you coerce a numeric value into a boolean variant the result is a 1 for any value other than 0. Be aware that VBScript and the browser that's containing it may not always handle booleans the same. In the example code shown in the following listing, the Alert statement of the Explorer browser displays the Boolean as a numeric value while Visual Basic Script's MsgBox procedure displays it as a keyword. MyBool = True Alert MyByte 'displays (-1) MsgBox MyByte 'displays 'True'

The Byte Sub-Type


The Byte sub-type is an 8-bit unsigned integer. It was first included with Visual Basic 4. Its main purpose was to replace the use of strings for containing binary data. Prior to Visual Basic 4, string data was a single byte unsigned integer that represented an ASCII character. This changed to the two byte Unicode system with Visual Basic 4 and made strings unreliable for carrying binary data. The advantage of the Byte sub-type in Visual Basic Script is limited to using it as an unsigned integer value up to 65535, or as a set of eight Boolean flags.

The Currency Sub-Type

The Currency sub-type is optimized for the highly accurate manipulation of currency values or any math that requires accuracy up to 15 whole number places and four decimal places. Internally, it is an 8-byte integer with a 4-digit fixed decimal place. The numeric range of the currency type is 922,337,203,685,477.5808 to 922,337,203,685,477.5807.

The Date Sub-Type


The Date sub-type is a 64-bit floating point number that can represent a date from 1/1/100 to 12/31/9999. The way it works is that each whole number represents a day and the decimal numbers represent time. Negative whole numbers count back from 12/30 1899 and positive whole numbers count forward from that date. Time is represented by the digits to the right of the decimal point with .0 equal to midnight and .5 equal to 12 o'clock noon. Date sub-types recognize input either as strings that represent dates or their numeric equivalents. Listing 16.1 shows a set of date representations and how they are displayed under different circumstances. Listing 16.1 The Different Ways a Date Value Can Be Handled Myname = 12345.123 Myname = cdate(myname) alert myname 'displays "10/18/33 2:57:07 AM" alert cdbl(myname) 'displays 12345.123 Myname = cdate("10-10-10") alert cdbl(myname) 'displays '3936' alert cdate(myname) 'displays '10/10/10' Myname = cdate("April 15, 1996") Alert Myname 'displays '4/15/96' Alert cdbl(myname) 'displays '35170'

The Double Sub-Type


The Double sub-type is an IEEE 64-bit double precision floating point number that can represent a range from 1.79769313486232E308 to 4.94065645841247E-324 in negative numbers, and 1.79769313486232E308 to 4.94065645841247E-324 in positive numbers.

The Integer Sub-Type


The Integer sub-type is a signed single byte integer value that ranges from 32,768 to 32,767. I would like to point out that there is no longer any speed advantage to using the Integer type over the Long in 32-bit environments and, of course, the Integer type has the disadvantage of a more limited value range.

The Long Sub-Type

The Long sub-type is a signed two-byte integer value. Its numerical range is from 2,147,483,648 to 2,147,483,647. Since Win95 and WinNT are 32-bit operating systems, they naturally do everything in 32-bit chunks. The long integer type no longer incurs a speed penalty over the integer type. I recommend that the Long be used everywhere you might have previously used the integer type.

The Object Sub-Type


The Object sub-type is a 32-bit address pointer reference to an OLE automation object instance. The ActiveX and Java controls are OLE Automation objects. You can set a reference to an object using the following syntax: Set MyObject = New OleObject At present, Visual Basic Script limits you to only the ActiveX and Java objects as OLE automation objects.

The Single Sub-Type


The Single sub-type is a 32-bit IEEE single precision floating point number. It has a numerical range of 6-3.402823E38 to 1.401298E-45 for negative values, and 3.402823E38 to 1.401298E-45 for positive values. Being a 32-bit number, it can show significant speed improvements over a double precision number in complex repetitive math that does not exceed the range of the single.

The String Sub-Type


The String sub-type is a continuous set of character values. In Visual Basic Script this can be up to 2 billion characters. Visual Basic Script only supports variable length strings, not the fixed length strings of the full version of Visual Basic. As noted in the Byte sub-type, Visual Basic strings should not be used to manipulate binary data as was done in previous BASICs since the string now utilizes two-byte Unicode characters that could corrupt binary data under the right circumstances.

When designing your Visual Basic Script, consider this: You are writing a script program that is intended for access over the limited bandwidth of the Internet. Your Visual Basic Script program will not be compiled or optimized in any way by the server or the browser. The more raw text that needs to be sent over the network, the longer it takes to load the page. Everything you can do to compact your code's use of text lessens the time to deliver the page to the client. This is not to say that you should write cryptic code, eliminate error trapping, or otherwise compromise the professionalism of your resulting product. I am just suggesting that you attempt to use the most efficient methods and algorithms you can devise to accomplish your task.

Working with Visual Basic Script's Variables


Back to the subject at hand! Besides the limitations of only one data type, Visual Basic Script does not provide for user-defined collection objects and user-defined types. This can be a severe limitation in a normal programming environment. But this is a limited scripting version of Visual Basic optimized for use within an HTML document with the idea of placing as small a load on the network as possible. There is also the innability to pass data by reference that requires your data variables to be global if you intend to use them from one procedure to another. You cannot pass changes to a procedural argument back to the caller. Of all the constraits in VBScript this is perhaps the greatest concerning the use of variables. It makes it very easy to have one procedure corrupt the data for another procedure. You are going to have to pay close attention when changing data values and you are going to have to validate data for both type and value.

Creating Variables
There are two ways to create variables. You can implicitly create them where needed in a program or explicitly declare them before use. The accepted practice among most professional programmers is to explicitly declare them. In addition to explicitly declaring them, Visual Basic Script also includes the Option Explicit statement as an insurance against misspelling variable names. When used, it requires explicit declaration of a variable before attempting to use it. This prevents the programmer from common mistakes such as reusing a variable name or misspelling a variable name only to go insane later on trying to figure out why a given variable always has incorrect results in it. I strongly suggest that you use the Option Explicit statement in all of your scripts to help you eliminate as many potential bugs in your programming efforts as possible. The Option Explicit statement must be the very first line in your script for it to work properly.

Determining Data Type


If you are in a situation where you need to know the data type of a value in a variant before you use it, Visual Basic Script provides a function that tests the variant for certain data types. The VarType() function returns an integer type value that represents the data type of the variant. A set of intrinsic constants within Visual Basic Script is provided so that you can easily write code to determine the data type without having to remember these integer values (see Table 16.1). Table 16.1 Visual Basic Script Constants for Return Values of the VarType() Function Constant vbEmpty vbNull Value Description 0 1 Empty of any value and not initialized Contains a null value

vbInteger vbLong vbSingle vbDouble vbCurrency vbDate vbString vbObject vbError vbBoolean vbVariant vbByte vbArray

2 3 4 5 6 7 8 9 10 11 12 17

Contains an integer value Contains a long integer Contains a single precision floating point value Contains a double precision floating point value Contains a currency type floating point value Contains a date type value Contains a string type value Contains a reference to an OLE automation object Contains an error Contains a boolean true or false value Contains a variant Contains a non-OLE object Contains a byte value

vbDataObject 13

8192 Contains an array

Given the information in Table 16.1 you might wonder what kind of situation you would want to use this VarType() function. How about error trapping? The example shown in Listing 16.2 sends a set of coordinates to a function that checks to see if the coordinates are within a given range of values, and returns a true or false based on that comparison. But it also checks to see if minimal values are being returned and returns an error value if these minimals are not met. Other possible uses include branching logic based on the type of data returned from a query. Listing 16.2 Passing an Error Value a Function Result <Script ="VBS"> <!-Sub Image1_MouseMove(a,b,x,y) blnSuccess = IsMyArea(x, y) If VarType(blnSuccess) = vbError Then MsgBox "An unknown error has occured" ElseIf blnSuccess = True then Aleret = "Click Here for More Information" End If End Sub Function IsMyArea(x, y) If x >0 and y> 0 then If x >100 and x <201 then IsMyArea = True

Else IsMyArea = False End Else IsMyArea = CVErr(5) End If End function - - > </Script> In the case of a variant of type Array, the value returned from VarType() is a binary combination of vbArray and whatever the contained data type is. That is to say that a variant array of string types would return the value vbArray plus vbString added together. To determine that a variable is a variant array you would use a logical AND. Then, to determine the data type you can use a select case statement to determine the data type of the array as Listing 16.3 does. Listing 16.3 Detecting Sub-Type of a Variant Array If VarType(MyValue) And vbArray then Select Case VarType(MyValue) - vbArray Case is vbEmpty Case is vbNull ... Case is vbByte End Select End If

Variable Naming Conventions


While using the VarType() function in the proceding chapter to ensure data type in your code is an excellent way of protecting individual procedures from fatal errors due to the inadvertant passing of the wrong type, you can also take preventative steps against this and other errors by using a sensible and consistant naming convention in your scripts. Clearly, if every variable is instantly recognized as to type and purpose by its name then misuse of that variable in your code becomes less likely. There are several different naming conventions floating around in the Visual Basic community and all have their merits, and you might even develop your own. What is important is that your VBScript is consistant in those conventions. Table 16.2 provides a suggested set of prefixes for data types. Table 16.2 Suggested VBScript Variable Naming Conventions Prefix Type bln byt Byte Example bytStateFlags = bytStateFlags And &H10

Boolean blnDataValid = True

cur dte dbl int lng obj sng str

Currency curTotal = curSubTotal + curSalesTax Date Double Integer Long Object Single String dteNextAppointment = NOW + 14 dblZPlot = 375.035 * 127.999 For intCount = 1 to intMaximum For lngCount = 1 to lngMaximum Set objMyDoc = Document sngXLocation = sngMyX * 2.5 strUserName = strFstName & " " & strLstName

In addition to the prefixes that identify the data type, I also recommend that you use names that clearly define the purpose of the data contained in the variable. Looking at Table 16.2 again you can see that the blnDataValid is a True/False condition of some state data's validity. If you have a set of data inputs that you validate either during input or during an attempt to submit it, this variable would represent the result of the data having been checked for valid type and range. Seems to be very obvious looking at it, but suppose I had named that same variable bDVal instead. If I had to maintain code with variables named like bDVal I would probably spend a lot of time finding out what each variable is supposed to represent as opposed to the more robust name of blnDataValid which fully describes data type and purpose.

Variable Scope
Variables in Visual Basic Script have three levels of scope: page level scope, script level scope, and procedure level scope. The script level variables are declared right at the beginning of the script and are available to all procedures within that page's script (see Table 16.3). Variables with a procedure level scope are declared in the procedure they are used in and are visible only within the context of that procedure. Outside of procedures you declare a variable as either Private or Public. The variable that is declared as Private is visible to only the procedures within the script it is declared in. The variable that is declared as Public is visible to all of the scripts on that HTML document (see Listing 16.4). Table 16.3 Variable Scoping in VBScript KeyWord Placement Dim Dim Private Public In Procedure Description of scope Limited to the procedure

Not in Procedure Visible throughout script Not in Procedure Visible throughout script Not in Procedure Visible throughout all scripts

Listing 16.4 Examples of Variable Scope

<SCRIPT LANGUAGE=VBS> <!-Option Explicit Dim MyName 'Script level variable Sub Main (ButtonName) 'ButtonName is Procedure Level Myname = ButtonName &"Ibrahim" End Sub Sub BtnHello_OnClick Main "Hello" Alert Myname End Sub Sub BtnGoodBye_OnClick Dim MyButton 'Mybutton is procedure level MyButton = BtnGoodBye.Value Main MyButton Alert Myname End Sub --> </SCRIPT> In the example script shown in Listing 16.4, MyName has a script level scope and is visible in both button click events. The ButtonName argument to the Sub Main procedure is a procedural level variable and is visible only to the Sub Main procedure. In the BtnGoodBye Click procedure, the MyButton variable is also limited in scope to the procedure. It is a commonly accepted programming practice to limit the scope of a variable as much as possible. With Visual Basic Script, you can pass values only by value. When you pass a variable by value, the procedure that it is passed to cannot pass the changes to the variable back up the call stack. The value is local only to the procedure. To be more specific, when you pass an argument by value, you are only passing the value contained in the variable to the procedure, and the procedure stores the value in a local replica of the variable. When you are passing a variable by reference then you are passing the address of the variable to the procedure, and the procedure directly accesses the passed variable's values. VBScript does not support passing values by reference at this time.

Literals, Constants, Structs


Visual Basic Script does not support constants or structs like the Type...End Type as in Visual Basic 4. You can either use literal values or define variables and populate them with values. Most programmers have learned to not use literals in their code due to the difficulty in maintaining such code. Instead, a good practice is to utilize constants to represent literal values throughout your projects. Since Visual Basic Script does not actually allow for constants, you have to use global variables that you initialize during runtime. Not a lot of difference in use from constants, just a slightly different way of doing it. But remember, unlike true constants, you can change the value of these variables during runtime so you should have some sort of naming convention that clearly marks them out as constants as in the example code in Listing 16.5.

Listing 16.5 Pseudo Constants 'pseudo constants Dim cstSunday Dim cstMonday Dim cstTuesday ... cstSunday = 0 cstMonday = 1 cstTuesday = 2 ... Sub WhatDayIsIt If DayOfWeek(cstSunday) then Alert "Sorry We are closed today" Else ...Do some code End If End Sub From Here... You have seen that VBScript uses Visual Basic's Variant data type as a catch-all utility variable for all other data types. The Variant is like a sack that you can drop anything you want into. But you have to be careful that you have a method in place to keep track of what each variable contains as your scripts become more complex and as you attempt to reuse code in other projects. Where this is really going to become a problem is in the use of the ActiveX Layout control in the development of drop in place functionality. You, or someone else, will develop a control for a particular purpose and expose certain properties and methods of that control for use by the main HTML document. Knowing what kind of data type is expected for a given property by just looking at the name of that property will go a long way in helping to write bug-free code.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us.

1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 16 - VBScript Operators


by Ron Schwarz

Operators are keywords and characters that tell the VBScript interpreter to act upon the values contained in variables, literals, and expressions. This chapter examines arithmetic, string, comparison, and logical operator groups. Each group is discussed in a separate section, and each section contains a short table listing the operators in that group. In this chapter
q q q q q q q q q q

Unsung heroes Operators are not particularly glamorous, but used judiciously can save lots of coding effort. Groups of operators Different types of operations require different operators. This chapter groups them by category. What they're for Find out uses for different types of operators. Understanding operators Learn how they work, and things to watch out for. Using operators See syntax and result details.

Using Operators
In most cases, you can view operators as behaving identically on expressions, variables, and literals. One important exception is the assignment operatoryou can only assign a value to a variable. (You can have a numeric literal or an expression on the left side of an equals sign, but only when performing a testfor example, If (A + B) = (C + D) Then...) Much of your VBS code depends on logical operations. A good understanding of the more commonly-used operators is essential. If you come from a background of programming in other

languages, you've undoubtedly got a good grasp of the subject, and only need to brush up on VBS syntax. If you're just getting into programming VBS from a background of HTML programming, it's time to dig in, and learn the principles of logical testing and bitwise operations.

Operator Precedence Throughout this chapter, you'll see extensive use of parentheses in example code. While it's frequently possible to rely on Operator Precedence rules (described below), you may find that your code is much more readable and you spend much less time debugging your apps if you are not overly sparing in your use of parentheses. Parentheses always override Operator Precedence rules. And, expressions are evaluated from the inside out, starting with the innermost set(s) of parentheses. Coercing evaluation this way eliminates ambiguityboth to you and to the VBS script execution engine. If you neglect to use sets of parentheses to force evaluation to take place according to your rules, VBS falls back on its default Operator Precedence rules. According to these built-in rules, the order of evaluation is:
q q q

Arithmetic operators (see following) Comparison operators (evaluated left-to-right) Logical operators (see following)

Arithmetic and logical operators, unlike comparison operators, are evaluated in specific order. The evaluation order for arithmetic operators is:
q q q q q q q q q

Exponentiation Unary negation Multiplication Division Integer division Modulo arithmetic Addition Subtraction String Concatenation (not an arithmetic operator, but evaluated in same order sequence)

The evaluation order for logical operators is:


q q

Logical negation Logical conjunction

q q q q

Logical disjunction Logical exclusion Logical equivalence Logical implication

Arithmetic Operators
The arithmetic operators are used with numeric variables and literals and expressions. (Since VBS at the moment has no constants, they are not an issue here.) The plus sign (+) can also be used as a string concatenation operator, but this usage is obsolete and should be used sparingly. The following table lists the Arithmetic Operators: Operator Definition * / \ Mod + ^ Unary negation Multiplication Division Integer division Modulo arithmetic Addition Subtraction Exponentiation

In addition to the arithmetic operators discussed in this chapter, VBS offers a rich selection of math functions. These are covered in greater detail in Chapter 22, "VBScript Language Elements."

Unary Negation
The Unary Negation () operator designates the negative value of a variable, number, or expression. Please note that the minus character is also used as the subtraction operator and is discussed later in this chapter. The following example returns 10 in B: A = 10 B = -A

Multiplication

The Asterisk (*) character is used to multiply two values according to the following syntax: Total = Item * Quantity

Division
The forward slash (/) is used when dividing one value by another. It returns either an integer or floating point value, as dictated by the actual operation. For coerced integer division, see the integer division operator description. The Division Operator is demonstrated in the following example. UnitPrice = TotalPrice / Quantity

Integer Division
The integer division (\) operator is used the same way as the division operator. However, it truncates any remainder, and only returns the integer part of the result. The following example returns 3: IntResult = 10 \ 3

Modulo Arithmetic
The Modulo Arithmetic (Mod) operator is used to return the non-integer part of a division operation. The following example returns 1: IntResult = 10 Mod 3

Addition
The plus sign (+) is used as the Addition Operator. As mentioned earlier, it can also be used as a string concatenation operator, but this usage should be avoided unless there is a specific need for the peculiarities it introduces. (When using the + sign between two variables, the expression can be rendered as either an addition operation or a concatenation operation, depending on the values and types of the two variables. Because of the uncertainties this creates, it's generally best to reserve use of the + sign for addition, and the & for concatenation.) The following example returns 10 in A: A=5+5

Subtraction
The minus sign () is used as the Subtraction Operator. It is important to avoid confusing this with its other use (as a unary negation operator). The following example returns 5 in A: A = 10 - 5

Exponentiation
The Exponentiation Operator (^) is used to raise one value to the power of another. The following example returns 256: Result = 2 ^ 8 Unlike multiplication, you must be careful about where you place exponentiation expressions reversing the order produces dramatically different results. The following example returns 64: Result = 8 ^ 2

String Operators
There is only one String Operator: the & string concatenation operator. Don't think of this as a real limitation, however. Unlike numbers, strings aren't really subject to "operations," per sefor example, you don't multiply one word by another. However, there is a rich set of string manipulation functions, and the comparison operators (described later in this chapter) apply to most variable types, including strings.

String Concatenation
The ampersand (&) is used for concatenating strings. Concatenation simply consists of joining two strings together. Concatenation does not join one string to anotherit returns a third string that represents the result of the operation. The original strings are left intact. The following example returns Ron's Computer: MyComputer = "Ron's" & " " & "Computer" In the preceding example, we used two concatenation operations in one expression. This is perfectly legaleach operation only works on two strings. The + sign can also be used to concatenate strings but its use is generally discouraged.

Comparison Operators
The Comparison Operators, as show in the following table, are used when testing expressions and

variables against each other or against other conditions such as True or False. Operator Definition = <> < > <= >= Is Equality Inequality Less than Greater than Less than or equal to Greater than or equal to Object equivalence

Equality
The equals sign (=) is used as the Equality Operator. It is also used as an Assignment Operator.

The = Assignment Operator You may have noticed that there is no section for assignment operators and no entry in any table for the equals sign in its assignment operator mode. This is due to some BASIC arcanathe equals sign is, strictly speaking, part of the Let statement. However, use of Let is optional in VB, and the only time you're apt to see it in use is when non-VB code (for example, other non-Microsoft dialects of BASIC) is ported over to VBS. In VB and VBS, X = 10 is functionally identical to (and more readable than) Let X = 10. (The Let X = 10 syntax should not be confused with Property Let settings in VB, which are not implemented in VBScript.)

The equals sign is used when testing one expression against another for equality. As with all comparison operators, the result is an implicit Boolean (True or False) result. If A = B Then is equivalent to the following code: If (A = True) And (B = True) Then EndIf

Due to the way VBS handles these tests, you do not have to test for explicit True, and, as demonstrated in the following code snippet, you don't even have to use the equality operator in some cases. If A Then EndIf In the preceding example, as long as A is non-zero (presuming that A is a numeric variable) the test succeeds. If you need to test against True (or any other specific value), you need to use the equals sign, as in the following: If A = 25 Then EndIf

Inequality
The < and > characters combine to form the Inequality Operator. They function opposite to the equality operator. The following example demonstrates their use: If CreditStatus <> FlaggedAccount Then EndIf In this example, as long as the two variables are not equal, the test passes. The inequality operator can also be used on strings. It performs a test based on ASCII value, which is case-sensitive. If you need to perform a case-insensitive test, you must use either Lcase or Ucase to assure that both values are of the same case. If the strings do not match, the result is True.

Less Than
The < character is used as the Less Than Operator. If the expression on the left side of the less than operator is less than the expression on the right, the test passes. In the following example, as long as the value in RPM is less than the value in Redline, the test passes: If RPM < Redline Then EndIf The less than operator can also be used on strings. It performs a test based on ASCII value, which is case-sensitive. If you need to perform a case-insensitive test, you must use either Lcase or Ucase to assure that both values are of the same case. Be careful, as differences in length can affect the results.

This can be a problem when strings contain numeric values, and different numbers of leading zeros further complicate matters.

Greater Than
The Greater Than Operator (>) is the opposite of the less than operator. If the expression on the left side of the > is higher, the test passes. In the following example, as long as Balance is higher than Limit, the test passes: If Balance > Limit Then EndIf The greater than operator can also be used on strings. It performs a test based on ASCII value, which is case-sensitive. If you need to perform a case-insensitive test, you must use either Lcase or Ucase to assure that both values are of the same case. The same concerns mentioned for the less than operator also apply here.

Less Than or Equal To


The Less Than or Equal to Operator (<=) can also be used on strings. It performs a test based on ASCII value, which is case-sensitive. If you need to perform a case-insensitive test, you must use either Lcase or Ucase to assure that both values are of the same case. The same concerns mentioned for the less than operator also apply here. This example will pass if the value in Amount is less than, or equal to the amount in Limit: If Amount <= Limit Then EndIf

Greater Than or Equal To


The Greater Than or Equal to Operator (>=) can also be used on strings. It performs a test based on ASCII value, which is case-sensitive. If you need to perform a case-insensitive test, you must use either Lcase or Ucase to assure that both values are of the same case. The same concerns mentioned for the less than operator also apply here. In this example, the test will pass if the value in Age is greater than or equal to the value in Minimum: If Age >= Minimum Then Endif

Object Equivalence The Is keyword is the Object Equivalence Operator. It tests two objects or object variables to if they are refer to the same object. The following code snippet demonstrates a test of Object Equivalence: Match= Handy Is LongFormName.LongControlName In this test, if Handy is an object variable that has been previously Set to a reference to LongFormName.LongControlName, Match will return True, otherwise, it will return False. Logical Operators This table defines the Logical Operators: Operator Definition Not And Or Xor Eqv Imp Logical negation Logical conjunction Logical disjunction Logical exclusion Logical equivalence Logical implication

The logical operators apply to Boolean expressions. The elements of a Boolean expression can be of any data typeit's not necessary to build a Boolean expression out of Boolean variables.

A Boolean Expression is an expression that returns either True or False (-1 or 0) as its result.

The And and Or operators wear two hats: they are used in simple tests of expressions and in bitwise Boolean operations. The differences are noted in the following respective sections. Each logical operator description contains a truth table that shows the results produced by all possible bit combinations.

A Truth Table is a list of all possible operations and results for a specific operator.

One additional factor comes into play with logical operations. When any value contains Null, the result is also Null. Null propagates through the operation. This is not shown in the truth tables, but should be taken into consideration if there is a possibility that any of your values might contain Null.

Logical Negation
Logical Negation (the Not keyword) is similar to unary negation, but, like all logical operators, is carried out on the bit level rather than on the value of the expression. It's easy to fall into the trap of using Not when testing expressions, and finding that things aren't working as they should. Not reverses all the bits in a variable, and is generally used against either True or False in Boolean tests. A common programming error is to look at the Not operator in the same context as the And and Or operators. While we can use And and Or to build a logical testing expression, we cannot do so cavalier with Not. For example, the following code does not work correctly: If (Balance < Limit) And (Lastname Not "Smith") Then EndIf For one thing, we can't "NOT" a string. And, even if we use numeric values, we'd still have a large unpredictability factor. There are some nifty uses for this operator, though. A variable (or a property) that needs to toggle between True and False can be easily managed with one simple line of code. The following line of code toggles the value of the Direction variable between True and False. This is much simpler than a complex "If Direction = True Then Direction = False Else..." block of code. Direction=Not Direction 'reverse direction The reason for this is simple: when we reverse the bits in False (0), we end up with True (1), and vice versa. Here is the Logical Negation Operator's truth table: Truth Table for Logical Negation Expression Result

False True

True False

Logical Conjunction
The And keyword is used as the Logical Conjunction Operator in VBScript. As with the logical disjunction (Or) operator, it has dual uses. You can apply any logical test against a clause of one expression And another, or you can use And to return a value representing a bitwise (bitwise means that the two values are tested one bit at a time) "Anding" of two values. The following example passes if both expressions evaluate to an implicit True: If (Total < Limit) And (AccountStatus = Current)Then EndIf The next example returns 127 in C, since the set bits that are common to both A and B equal 127: A = 127 B = 255 C = A And B This is the truth table for the Logical Conjunction Operator: First Expression Second Expression Result False False True True False True False True False False False True

Logical Disjunction
Or is used as the Logical Disjunction Operator. Like And, it is used when testing expressions and also for bitwise Boolean operations. The comparison test in the following example passes if either of the expressions evaluate to an implicit True: If (Moves > GameLimit) or (GameTime > TimeOut) then

EndIf The next example always returns the lowercase form of whatever (single letter) string literal is passed: LowerCase = Chr(Asc("A") or 32) Here is the Logical Disjunction truth table: First Expression Second Expression Result False False True True False True False True False True True True

Logical Exclusion
The Xor (Exclusive Or) keyword is used as the Logical Exclusion Operator. The logical exclusion operator is similar to the Or operator, with one significant difference. Whereas Or evaluates when either or both bits are set (remember, we're comparing values one bit at a time), Xor evaluates when only one bit is sethence, its "exclusive" qualification. The Xor Logical Exclusion Operator is frequently used for simple encryption routines, since a byte Xored by another number produces a number that is restored when Xored by the same number. By Xoring a string one character at a time against each character of a password string, an encrypted string results. And, when Xoring the encrypted string by the same password, the plaintext string is restored. It is interesting to note that any value Xored with itself results in False. The first routine in Listing 16.1 encrypts the string contained in PlainText, and places the encrypted value in CryptText. The second routine reverses the process, and places the decrypted string in NewText. Listing 16.1 Logical Exclusion Example PlainText = "Test Text" Password = "Swordfish" For C = 1 To LEenPassword$) CryptText = CryptText + Chr(Asc(MIidPlainText, C, 1)) _ Xor Asc(Mid(Password, C, 1)))

Next For C = 1 To Len(Password) NewText = NewText + Chr(Asc(Mid(CryptText, C, 1)) _ Xor Asc(Mid(Password, C, 1))) Next The Logical Exclusion truth table follows: First Expression Second Expression Result False False True True False True False True False True True False

Logical Equivalence
The Eqv keyword is used as the Logical Equivalence Operator. This operation is similar to And, but, in addition to evaluating when both bits are set, it also evaluates when both bits are not set. If both bits are the same (either True or False) the expression passes evaluation. Here is the Logical Equivalence Operator truth table: First Expression Second Expression Result False False True True Logical Implication Imp is used as the Logical Implication Operator. If identical bits in both expressions are True or if bits in the righthand expression are True, the operation evaluates as True. Here's the Logical Implication truth table: First Expression Second Expression Result False False True True False True False True True True False True False True False True True False False True

From Here...
Operators are used in every aspect of VBScript programming. Check Chapters 11-20 for general coverage of language features. And, specifically, consult these chapters for more information:
q

q q

Chapter 15, "VBScript Data Types and Variables," contains valuable information on manipulating data in VBScript. See Chapter 19, "VBScript Procedures." Procedures are the central building block for code. Chapter 22, "VBScript Language Elements," explains string manipulation functions, math functions, and other useful language features of VBS.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 17 - VBScript Control of Flow and Error Handling


by Ibrahim Malluf

Visual Basic Script provides an almost complete set of sequential, looping, and branching structures. VBScript also only allows the 'On Error Resume Next' error handling structure, limiting Visual Basic Script to inline error control. That means Visual Basic programmers who are used to branching to labeled error-handling routines will have make do with this limited approach. Despite this major limitation on error handling, Visual Basic Script is a very robust programming platform for adding client-side scripting capabilities. Let us review the fundamental structures that comprise the basis of structured programming techniques and how they are implemented in Visual Basic Script.
q q

q q q q

Programming Structures in Visual Basic Script Here we discuss the building blocks of structured programming available in Visual Basic Script. Error Handling in Visual Basic Script A discussion on error-handling techniques available in Visual Basic Script. Applying Visual Basic Script to HTML This section quickly gets you into applying Visual Basic Script to an HTML document while also introducing the use of ActiveX controls.

Programming Structures in VBScript


Modern programming techniques revolve around structures. VBScript includes the three main types of structures: sequential, looping, and conditional branching. Different combinations and variations of these three structures are the tools that you'll use to accomplish the programming task at hand. What follows is description of each structure included in Visual Basic Script.

Sequential Structures
Sequential structures are the simplest of programming structures. They are the lines of code that actually perform the calculations, state changes, printing, input and output, and other required operations. They can also be branching instructions, such as a function or subroutine call. Generally

speaking, sequential statements are almost always contained within other more complex structures. Listing 18.1 shows a set of five example sequential structures. Listing 18.1 Simple Structure Statements Username = "John Doe" UserID = "ABC123" MyRate = A * (C1/C2) MyResult = Myfunction(MyRate) Call AnySub(Arg1, Arg2, Arg3)

Looping Structures
Looping structures cause program execution to repeat in a continuous loop until some condition is met. In Visual Basic Script, there are four different looping structures. They are called looping structures because the one common feature among them is that they repeat the same section of code until something causes the loop to end. The Do...Loop Structure The Do...Loop structure continually repeats a block of code until a specified condition is met either before each loop or after each loop. What determines if the loop runs at least once depends on where the structure's conditional is placed and whether that conditional is a While or Until conditional. Let's take a look at the different ways you can construct a Do...Loop along with some example code that shows how the particular style can be used. The following code shows all of the Do...Loop structure's possible syntactical variations. The conditionals that break the loop can be at the beginning, middle, or end of the loop. In the beginning or end of the loop structure you would use the While or Until keywords to indicate the conditional. In the middle of the loop you can use an If...Then structure to break out of the loop with an Exit Do statement as part of the If...Then's statements. DO [WHILE|UNTIL condition] [statements] [EXIT DO] LOOP [WHILE|UNTIL condition] The following example runs only if the condition is met in the beginning and repeats as long as the condition is met. DO WHILE condition

[statements] LOOP An example of this structure is shown in Listing 18.1. Here the statements inside of the Do...Loop will execute only if intPlace is less than or equal to 8 and repeat until intPlace is greater than 8. Also note that the Do...Loop will immediately exit if the intCount value exceeds the upper bounds of the strData array. Listing 18.1 A Do While Example Do While IntPlace =< 8 If IntCount > Ubound(strData) then Exit Do intPlace=instr(strData(intCount),";") Call MyProcess(intPlace,intCount) IntCount=IntCount + 1 Loop The following runs only if condition is not met and repeats as long as the condition is not met. DO UNTIL condition [statements] LOOP [statements] An example of this form of the Do...Loop structure is shown in Listing 18.2. Note that it is a minor modification of Listing 18.1 that does the exact same thing only using the Until keyword instead and will also repeat as long as intPlace is less than 8. Listing 18.2 A Do Until Loop Do Until IntPlace > 8 If IntCount > Ubound(strData) then Exit Do intPlace=instr(strData(intCount),";") Call MyProcess(intPlace,intCount) IntCount=IntCount + 1 Loop The next example's Do...Loops always run at least once regardless of the loop's conditional requirements. This is because the conditional is not checked until the end of the loop's statements.

In this example a While statement is used for the conditional. In this case the loop will repeat as long as the condition is met. DO [statements] LOOP WHILE condition Continuing to use a slight modification of the same sample code, Listing 18.3 shows a Do...Loop that will always execute once, and if the condition is met will repeat again. Listing 18.3 A Do Loop While Example Do If IntCount > Ubound(strData) then Exit Do intPlace=instr(strData(intCount),";") Call MyProcess(intPlace,intCount) IntCount=IntCount + 1 Loop While IntPlace =< 8 Finally the Do...Loop Until structure will repeat as long as the condition is not met. DO [statements] LOOP UNTIL condition Listing 18.4 shows the same example code this time using an Until condition structure. Listing 18.4 A Do Loop Until Example Do If IntCount > Ubound(strData) then Exit Do intPlace=instr(strData(intCount),";") Call MyProcess(intPlace,intCount) IntCount=IntCount + 1 Loop Until IntPlace => 8 Figure 18.1 demonstrates the structure of the Do...Loop process. FIG. 18.1

Logic Flow diagram of the Do...Loop structure.

Beware The Endless Loop! Make sure your looping structures have an explicit ending condition that must occur! When using a Do...Loop or While...Wend make sure that these loops have a definite ending condition; otherwise, you could end up locking up the browser from further interaction with the user. VBScript does not have the equivalent of a Visual Basic DoEvents() function, so there is no way to break out of a loop or allow other operations outside of the loop to occur.

These looping structures are used to repeat a given set of code based on a certain condition. The condition is usually the result of some calculation or other operation within the loop. It is possible, with multiple threads running in an application, for the condition to be affected from another operation independent of the Do...Loop itself, though relying on this can be dangerous. Looping structures must eventually arrive at a condition that allows the loop to end; otherwise, your application could lock up and stop responding to the user. This is especially true in Visual Basic Script because there is no mechanism like a DoEvents() function to allow breaking out of a loop through user intervention. Internet Explorer 3.0 will, after a particular operation has been looping for a while, ask if you want to end the script, but don't depend on other browsers to allow for this. Make sure your looping structures have a definite ending condition.

For...Next
The For...Next loop has a counter that is initialized to some value and then increments or decrements that counter for every iteration of the loop until it has reached some specified value. See Figure 18.2 for a diagram of the logic flow of a For...Next loop. The following code shows the syntax for For...Next loops: FOR counter = start TO finish STEP rate [statements] [EXIT FOR] NEXT The counter is the numeric value being incremented or decremented, start is the starting value of the counter, finish is the final value that the counter either increments or decrements to, statements are the code statements to be executed within the loop, and rate is the amount that the counter's value

changes with each interation. Figure 18.2 provides a logic flow diagram of a For...Next loop. FIG. 18.2 The Logic Flow Diagram of a For...Next loop. The STEP rate argument is optional and is required only if the rate of change is to be other than an increment of 1 per iteration. If you want the value of counter to increment 5 every interation, you use STEP 5 as part of the statement. If you want to decrement the count by 5, then use STEP -5.

In Visual Basic the placing of the counter name right after the Next statement has been a normal programming practice that actually saved CPU cycles that were noticable in long iterations of a loop. In VBScript this will produce an error because placing the counter after the Next statement is not supported.

While...Wend
While...Wend loops through a group of statements as long as a given condition is true. If the condition is True, then the statements between the While...Wend execute and return to the While statement to check if the condition is still True. If the condition is not True, execution resumes at the first line after the When statement. You can nest While...Wend statements. The syntax for While... Wend is shown in the following code: WHILE condition [statements] WEND condition is any operation that results in True or False. statements are the code statements to be executed within the loop. The example code in Listing 18.5 parses a string displaying each set of characters between ampersands. When it reaches the word "Stop" the loop ends. Listing 18.5 Using the While...Wend Loop Dim strMyTest strMyTest = "This&While...Wend&Loop&Will&Now&Stop&test5&test6" Sub btnTest_OnClick Dim strMyWord

Dim lngStart Dim lngEnd Dim lngLength lngStart = 1 While strMyWord <> "Stop" 'find position of seperator lngEnd = instr(lngStart, strMyTest, "&") 'determine length of word lngLength = lngEnd - lngStart 'extract word from string strMyWord = Mid(strMyTest, lngstart, lnglength) 'display extracted word msgbox strMyWord 'move start pointer to beginning of next word lngstart=lngend+1 Wend End Sub Figure 18.3 shows the logic flow diagram of the While...Wend statement. FIG. 18.3 The Logic Flow Diagram of the While...Wend loop. That completes the looping structures for Visual Basic Script. The next structure type is a conditionalbranching structure, known as the IF...THEN...ELSE structure.

Conditional Branching Structures


Conditional branching structures cause the flow of program logic to change according to a specified set of criteria. In VBScript there are two conditional branching structures, the If...Then...Else structure and the Select Case structure. If...Then...Else What an If...Then...Else conditional-branching structure essentially does is this: if a condition is met, a group of statements executes. If the condition is not met and there is an ELSEIF condition that is met, then those statements immediately following the ELSEIF execute. There can be multiple ELSEIF conditionals within the structure allowing for a cascading set of If...Thens until a condition is met. Finally if none of the previously stated conditions are met, you can have an ELSE group of statements that executes. The following code shows the syntax for the If...Then...Else structure (see fig. 18.4): IF condition THEN

[statements] [ELSEIF condition THEN] [statements] [ELSE] [statements] END IF condition is any operation that results in True or False. statements are the code statements to be executed within the branch. FIG. 18.4 The logic flow of the If....Then...Else conditional-branching structure. You can have as many Else If...Then statements as needed in your script logic. You should always try to have an Else condition; at least consider the need for one carefully when constructing your logic. I automatically include it in any multiline If...Then structure and remove it only after I have positively identified that it is not needed. Listing 18.6 shows an exanple If...Then...Else that includes an If, ElseIf, and Else condition. The purpose of the example is to ensure that a value entered into a textbox is within a valid set of bounds before passing it to the rest of the program through the lngMLat variable. If the value entered is not valid then the previous value contained in lngMLat replaces the text in txtMLat. If the value entered is valid then the entered value replaces the value in lngMLat. Listing 18.6 An Example If...Then...Else Structure Sub txtMLat_OnChange 'make sure latitude is within boundries if txtMLat.Value < 25 then msgbox "Lattitude is Outside Continental US" 'revert to previous value txtMLat.Value= lngMLat ElseIf txtMLat.Value > 48 then msgbox "Lattitude is Beyond the Contiguous US" 'revert to previous value txtMLat.Value= lngMLa Else 'Valid entry so post it to lngMlat lngMLat=txtMLat.Value End If End Sub

The Select Case Structure The Select Case structure takes a Value and compares that value to a list of conditions called Cases. The code within the first Case that matches the value gets executed. If there is a Case Else condition included in the structure then the code in that case will execute if none of the other cases matched the value. Here is the syntactical representation of the Select Case structure: SELECT CASE testexpression [CASE expressionlist-n [statements-n]] . . . [CASE ELSE expressionlist-n [elsestatements-n]] END SELECT testexpression is any value or expression that represents the conditional critria CASE is any expression that matches the criteria contained in testexpression expressionlist is an expression or value to be compared with the criteria identified in testexpression statements is the code to execute for the given expression. The Select Case structure is well suited to situations where there is a large list of possible conditions to match up to. Listing 18.7 shows an example Select Case being used in conjunction with a Popup Menu control. Listing 18.7 Using the Select case Structure sub IeMENU1_Click(ByVal x) select case x case 1 'zooms the map in by a factor of 10x Parent.Frames(0).MAPTOOL.cmdZOOMIN.Value=True case 2 'zooms the map out by a factor of 10x Parent.Frames(0).MapTool.cmdZOOMOUT.Value=True

case 3 'resets map back to default coordinates Parent.Frames(0).MapTool.txtMLat.Text = 35.02 Parent.Frames(0).MapTool.txtMLon.Text = -106.0075 Parent.Frames(0).MapTool.cmdShowMap.Value=True case 4 'no action here. allows user to close menu case else 'no else situation end select The code shown in Listing 18.7 compares the index of the menu item selected to a set of cases and executes the code where the case matches. Note that in this example I have a Case Else with no code to execute but a note saying that no else situation exists. On final review of this code, satisfied that there are no Else conditions to account for, I would remove the Case Else condition. Putting it there when I first write the skeleton structure reminds me to make sure that there are no possible conditions that I have overlooked and to allow for them if they do indeed exist. This concludes the text on logic flow control for VBScript. All of the structures shown in this section are the building blocks that you use to construct your program logic. The next section covers the techniques of handling your program logic when errors occur.

Error Handling
Visual Basic Script allows only inline error handling in its present incarnation. What this means is that you must immediately check for an error condition after each statement that might possibly cause an error. The error handler is invoked in the following manner: On Error Resume Next [Statement] If Err then [statements] Else [statements] End If Now some programmers prefer this style as opposed to using jumps to labels that handle errors. Myself, I prefer to be able to allow for only one place to enter a routine and one place to exit it using

the following code structure: Sub MySub () On Error Goto BadMySub [statements] ExitMySub: [exit code statements] Exit Sub BadMySub: [error handler statements] If fixed THEN Resume Else Resume ExitMySub End If End Sub The advantage of the latter approach is the ability to provide an area for cleanup code that always executes regardless of any other circumstances within the procedure. With the inline method, if the error is fatal then you must exit immediately where you have determined this error to be fatal. If there is cleanup code that has to be included then you must repeat that code everywhere that this kind of error exit occurs. The opportunity for introducing even more errors due to procedural complexity is present. But inline error handling is what is provided in the current incarnation of VBScript. The ERR object provides two methods and five properties, listed in Table 18.1. Table 18.1 The ERR Object's Properties and Methods Name Type Description

Description Property String containing a description of the error.

HelpContext Property Long integer pointing to a context in a help file. HelpFile Number Source Raise Clear Property String containing the path to the relevant help file. Property Long integer indicating the error number. Property The name of the object causing the error. Method Causes a specified error to occur. Method Clears the ERR object of error status.

The Description property contains a short description of the error that was generated. You can use this string in a message box or an alert box to inform the user that an error has occurred. The HelpContext property provides a jump to a help topic within a specified help file when the user presses F1 or clicks the Help button on an message box. If no context is provided, it defaults to the contents window of the help file. The HelpFile property of ERR object is a fully qualified path to a help file. If no help file is specified, then the browser's default help file is invoked. The Number property corresponds to a Visual Basic error number or a user-defined error number and is specific to the type of error generated. This property is usually checked to determine the error that has occurred, and program logic is usually branched off accordingly. The Source property contains the name of the object where the error originated. The Raise method has the following syntax: object.RAISE (number[,source,description,helpcontext,helpfile]) object is always the ERR error object. number requires a long integer that specifies the error being raised. source is an optional string naming the object that originated the error. description is an optional string describing the error. helpcontext is an optional long integer pointing to a help topic in the specified help file. helpfile is an optional string specifying the full path to a relevant help file. The Raise method is used to create an error condition in your code. In the context of Visual Basic Script, you can use this method to test and debug your own error handling code. It's original purpose was to generate a user-defined error condition in the Visual Basic environment from an OLE Automation object. Since Visual Basic Script does not allow you to create Automation objects, the use of the Raise method is probably limited to debugging your script code. The Clear method clears all of the property settings of the ERR object. An example of the Err.Object's use is given in Listing 18.8. This is a rewrite of the code shown in Listing 18.7. The While...Wend loop had a major flaw in it. Before going any farther, go back to that listing and see if you can determine what that flaw in that While...Wend loop was before reading on. Listing 18.8 ERROBJ1.HTMDoing Inline Error Handling with the Error Object <SCRIPT LANGUAGE="VBScript"> Dim strMyTest strMyTest = "This&While...Wend&Loop&Will&Now&Create&An&Error&" Sub btnTest_OnClick

Dim strMyWord Dim lngStart Dim lngEnd Dim lngLength lngStart = 1 lblDisplay.Caption="" While strMyWord <> "Stop" 'provide for possible errors On Error Resume Next 'find position of seperator lngEnd = instr(lngStart, strMyTest, "&") 'determine length of word lngLength = lngEnd - lngStart 'extract word from string strMyWord = Mid(strMyTest, lngstart, lnglength) 'check for an error condition in the string parser If lngEnd = 0 then 'error 99 is a user defined error Err.Raise 99, "btnTest_Click","No STOP found in string" End If 'this checks for any error either user defined 'or system error If Err then 'show th user the problem Msgbox Err.Description, 48, Err.Source 'end the WhileWend now Exit Sub End If 'display extracted word msgbox strMyWord lblDisplay.Caption=lblDisplay.Caption & " " & strMyWord 'move start pointer to beginning of next word lngstart=lngend+1 Wend End Sub </SCRIPT> The flaw in Listing 18.7 was that there was the possibility of an endless loop if the strMyTest string did not contain a "Stop" in it. Or if the string was improperly formatted or empty an endless loop could also occur. So in Listing 18.8 I rewrote the code with an error handler that will catch either of these conditions and log them as an error and exit the subroutine. I created a user defined error using the number 99 and provided a description of the error for later display. I then check for an error condition, display it and exit the procedure. The example in Listing 18.8 shows how to use the Raise method of the Err object for indicating an actual error condition in the code. You could also use the Raise method as an error assertion for

testing your program's code ability to handle various error by introducing specific errors at strategic places with this method and observe the outcome of that contrived error.

Applying Visual Basic Script to HTML


Now we can get into some Visual Basic Script examples that will give you a taste of what is possible. If you have had any experience with HTML you know that up until recently almost all activity was on the server side of things. HTML has been getting more and more capability added with each revision. But still it lacks the essentials of a good programming language. Visual Basic Script gives your HTML documents the client-side capabilities that HTML doesn't have.

The Rotating Labels Example


To get you started with a quick and impressive example, we will create a Web page with three rotating labels that display the current angles of the labels. We will also have the point size of the label text expand and contract. The Page Layout for the Rotating Labels Example The first order of things is to place all non-script elements on the page. Using a text editor like Notepad enter the code in Listing 18.8. Listing 18.8 ROTATELABELS.HTMHTML Portion of an HTML Document that Shows How to Place ActiveX Controls and Other Items on the Document

<HTML> <HEAD> <TITLE>Rotating Labels</TITLE> </HEAD> <BODY BGCOLOR="TEAL"> <OBJECT classid="clsid:99B42120-6EC7-11CF-A6C7-00AA00A47DD2" id=sprlbl4 width=650 height=40 align=CENTER > <param name="_extentX" value="50" > <param name="_extentY" value="700" > <param name="angle" value="0" > <param name="alignment" value="3" >

<param name="BackStyle" value="0" > <param name="caption" value="ROTATING LABELS EXAMPLE"> <param name="FontName" value="Arial"> <param name="FontSize" value="32"> <param name="FontBold" value="1"> <param name="frcolor" value="2552500"> </OBJECT> <HR> <CENTER> <INPUT TYPE=BUTTON VALUE="&Change Angle" NAME="BtnchangeAngle"> <INPUT TYPE=TEXT VALUE="Running" NAME="txtBox" SIZE = "30"> <BR><BR><BR> </CENTER> <OBJECT classid="clsid:99B42120-6EC7-11CF-A6C7-00AA00A47DD2" id=sprlbl1 width=200 height=200 align=left > <param name="_extentX" value="50" > <param name="_extentY" value="500" > <param name="angle" value="0" > <param name="alignment" value="2" > <param name="BackStyle" value="0" > <param name="caption" value="My Label"> <param name="FontName" value="Arial"> <param name="FontSize" value="20"> <param name="FontBold" value="1"> <param name="frcolor" value="16791935"> </OBJECT> <OBJECT classid="clsid:99B42120-6EC7-11CF-A6C7-00AA00A47DD2" id=sprlbl2 width=200 height=200 align=left > <param name="_extentX" value="50" > <param name="_extentY" value="700" > <param name="angle" value="0" > <param name="alignment" value="2" > <param name="BackStyle" value="0" > <param name="caption" value="My Label"> <param name="FontName" value="Arial"> <param name="FontSize" value="20">

<param name="FontBold" value="1"> <param name="frcolor" value="2552500"> </OBJECT> <OBJECT classid="CLSID:99B42120-6EC7-11CF-A6C7-00AA00A47DD2" ID=sprlbl3 width=200 height=200 align=left > <param name="_extentX" value="50" > <param name="_extentY" value="700" > <param name="angle" value="110" > <param name="alignment" value="2" > <param name="BackStyle" value="0" > <param name="caption" value="My Label"> <param name="FontName" value="Arial"> <param name="FontSize" value="20"> <param name="FontBold" value="1"> <param name="frcolor" value="96711935"> </OBJECT> <OBJECT classid="clsid:59CCB4A0-727D-11CF-AC36-00AA00A47DD2" id=timer1 align=middle > <param name="Interval" value="100"> <param name="enabled" value="True"> </OBJECT> The code in Listing 16.3 places several label controls, a button control, and a text box on the form; the background color is set to teal. What we are going to do here is have three of the labels rotate their text in a circular pattern while changing the text to reflect the angle that they are currently at. Clicking the button control starts and stops the rotation. The text control's text changes to Running when the labels rotate and displays the current angle when the rotation stops. The Visual Basic Script for the Rotating Labels Example The Visual basic Script portion of this example contains two procedures. The first procedure is an OnClick event of a button control. It utilizes a single If...Then...Else structure to toggle the timer control's enable property on and off. The second procedure is a timer event that contains a For...Next looping structure that iterates through the array of three label controls. Within the For...Next loop there are two If...Then structures. The first If...Then checks to see if the Icount property of the For... Next loop is an even or odd number and selects the direction of the rotation accordingly. The second If...Then loop compares the font size of the label against the maximum 20-point size points and increases or lowers the label's fontsize depending on the outcome of that comparison. Listing 18.9

shows the VBScript portion of the document that actually accomplishes these tasks. Listing 18.9 ROTATELABELS.HTMVBScript Portion of ROTATELABELS.HTM

<SCRIPT Language="VBScript"> <!-- Option Explicit Sub BtnchangeAngle_OnClick 'toggle the timer on and off with 'each subsequent click of the button 'and change the textbox's value to 'reflect the label's condition. If timer1.Enabled Then timer1.Enabled = false txtBox.Value ="Stopped at " & sprlbl1.Angle & " Degrees" Else timer1.Enabled = true txtBox.Value ="Running" End if End Sub sub timer1_timer On Error Resume Next 'create an array of lables and 'populate the array. Dim MyLabels(2) Dim Icount Set MyLabels(0) = sprlbl1 Set MyLabels(1) = sprlbl2 Set MyLabELs(2) = sprlbl3 'iterate through each label in the array For Icount = 0 to 2 'rotate element 0 and 2 clockwise and 'rotate element 1 counter clockwise IF Icount\2 <> Icount/2 then MyLabels(Icount).Angle = (MyLabels(Icount).Angle + 5) mod 360 Else MyLabels(Icount).Angle = (MyLabels(Icount).Angle - 5) mod 360 End If 'change the label text to reflect the current angle MyLabels(Icount).Caption = "My Angle Is " & MyLabels(Icount). Angle 'allow the font size to increase to 20 point

'then set it back to 6 points and start over If MyLabels(Icount).FontSize < 20 then MyLabels(Icount).FontSize = MyLabels(Icount).FontSize +2 Else MyLabels(Icount).FontSize = 8 End if Next If Err then MsgBox Err.Description End if end sub --> </SCRIPT> </BODY> </HTML> Save the document as ROTATELABELS.HTM and load it into your Internet Exporer 3.0 browser. Click the Change Angle button. The three labels on the bottom should start rotating the text in opposite directions. So this isn't rocket science but I just wanted to get you started with a simple script that utilized a looping structure and a conditional-branching structure. See Figure 18.5 for an idea of what the Web page should look like. FIG. 18.5 The Rotating Labels from Listing 18.9.

Client-Side Data Validation Example


Now let's move on to a more realistic and practical example of using Visual Basic Script. In the past, when a Web page was used for data entry, the user entered their data and clicked the Submit button. The data was then sent to the Web server; the server submitted the data to a server-side program, such as Perl, or a CGI script. If the data was missing items or improperly submitted, then the server-side script sent an error page back to the server that, in turn, sent the page back to the user informing him that his data was invalid. Given all the traffic on the Internet lately, this procedure could cause a considerable delayjust to find out you forgot to enter something or that there was a typo. Visual Basic Script gives you the ability to write pages that provide immediate client-side validation of data. When the user clicks that Submit button, your script can immediately validate the data for proscribed format and content. This is the theme of this chapter's next example. I make extensive use of If...Then structures in it. I also use a For...Next structure to iterate through the characters in a phone number field, formatting and validating it as I go. The Page Layout of the Client-Side Data Validation Example The HTML code for formatting the document includes two ActiveX label controls, two command

buttons, eight text entry controls, and a HTML table. Open a text editor and enter Listing 18.10's code for the body of the page. Listing 18.10 CH7_3.HTMHTML Code for the Client-Side Validation Page

<HTML> <HEAD> <TITLE>Client-Side Validation</TITLE> </HEAD> <BODY BGCOLOR="TEAL"> <CENTER> <OBJECT classid="clsid:99B42120-6EC7-11CF-A6C7-00AA00A47DD2" id=sprlbl4 width=700 height=40 align=CENTER > <param name="_extentX" value="50" > <param name="_extentY" value="700" > <param name="angle" value="0" > <param name="alignment" value="3" > <param name="BackStyle" value="0" > <param name="caption" value="Client-Side Data Validation"> <param name="FontName" value="Arial"> <param name="FontSize" value="48"> <param name="FontBold" value="1"> <param name="frcolor" value="2552500"> </OBJECT> <HR> <TABLE BGCOLOR="#FFFFCC" WIDTH=565 ALIGN=CENTER> <TR><TD BGCOLOR=NAVY ALIGN=LEFT> <FONT COLOR=FFFFCC>PLEASE ENTER YOUR DATA..</TD> <TD BGCOLOR=NAVY ALIGN=RIGHT></TD></TR> <TR><TD>NAME</TD><TD><INPUT TYPE=TEXT VALUE="" NAME="txtBoxName" SIZE = "65"></TD></TR> <TR><TD>ADDRESS1</TD> <TD><INPUT TYPE=TEXT VALUE="" NAME="txtBoxAddr1" SIZE = "65"></TD></TR> <TR><TD>ADDRESS2</TD> <TD><INPUT TYPE=TEXT VALUE="" NAME="txtBoxAddr2" SIZE = "65"></TD></TR>

<TR><TD>CITY,STATE,ZIP</TD> <TD><INPUT TYPE=TEXT VALUE="" NAME="txtBoxCity" SIZE = "35"> <INPUT TYPE=TEXT VALUE="" NAME="txtBoxState" SIZE = "5"> <INPUT TYPE=TEXT VALUE="" NAME="txtBoxZip" SIZE = "15"></TD></TR> <TR><TD>PHONE, FAX</TD> <TD><INPUT TYPE=TEXT VALUE="" NAME="txtBoxPhone" SIZE = "30"> <INPUT TYPE=TEXT VALUE="" NAME="txtBoxFax" SIZE = "30"></TD></TR> </TABLE> <INPUT TYPE=BUTTON VALUE="SUBMIT ENTRY" NAME="BtnSubmit"> <INPUT TYPE=BUTTON VALUE="CANCEL ENTRY" NAME="BtnClear"> <OBJECT classid="clsid:99B42120-6EC7-11CF-A6C7-00AA00A47DD2" id=sprlbl5 width=600 height=30 align=CENTER > <param name="_extentX" value="50" > <param name="_extentY" value="700" > <param name="angle" value="0" > <param name="alignment" value="3" > <param name="BackStyle" value="0" > <param name="caption" value=""> <param name="FontName" value="Arial"> <param name="FontSize" value="18"> <param name="FontBold" value="1"> <param name="frcolor" value="2552500"> </OBJECT> </CENTER> If you haven't worked with HTML tables before, the code in Listing 16.5 gives you some idea just how easy they are to use. See Appendix B for more detailed information on tables.Figure 18.6 gives you an idea of what the resulting table looks like. FIG. 18.6 The Client-Side Data Validation page. The Visual Basic Script for the Client-Side Validation Example

The Visual Basic Script is broken into two sections. The first section, Listing 18.11, contains the code underlying the two command buttons. It's short, easy to understand, and knows nothing about the validation functions that it calls. The sole purpose of the Submit button is to call the CheckAll() validation function; if it returns a True value, submit the data; and if it returns a False value, alert the user that there is a problem. The Clear button simply calls a routine that clears out all data on the page so that the user can start over with a clear page. What this means is that this first script is entirely independent of the underlying data structures and validation routines. If the data-entry requirements change at a later date, they only have to be changed in the actual validation functions contained in the second script. The more you can encapsulate functionality and limit the scope of data, the more secure your application is from inadvertently introducing errors by changing something in one place that is dependent on something in another. By encapsulating your code as much as possible you protect yourself from cascading errors in design. Listing 18.11 shows the first script. Listing 18.11 CH7_3.HTMCommand Button Script for Client-Side Data Validation

<SCRIPT LANGUAGE="VBScript"> <!-'================================================== ' Event Code '================================================== Dim IsValidData Dim MyErrorNotes 'the data is checked for validation 'when the user attempts to submit the 'data. Sub BtnSubmit_OnClick 'If CheckAll returns a true 'you would submit the data 'to whatever processing is required 'then clear out the entry fields If CheckAll() Then MsgBox "Your Data has been accepted" ClearAll Else 'if data is invalid warn the user MsgBox "Error in Data Entry" End if 'tell exactly what needs to be 'corrected NotifyUser

End Sub 'allow the user to clear the 'entry fields Sub BtnClear_OnClick ClearAll End Sub --> </SCRIPT> I know, there's not a lot there. But this is the idea behind encapsulating your code. Notice that the procedure names clearly state their purpose in life. CheckAll() means to check all of the data, ClearAll means to clear all the data out, and NotifyUser notifies the user of the current status. The alerts that are used here are solely for demonstration and should be replaced with code that does something like submitting the data to the server. The second script is much more involved, though still pretty simple. There are four procedures in the script. I present them in three sections. The first section contains the ClearAll and NotifyUser procedures. The third and fourth sections each contain one considerably more complex procedure. The ClearAll and NotifyUser Procedures The ClearAll procedure is very straightforward, using only sequential statements that sets text values and captions to empty strings. The NotifyUser procedure uses a simple If...Then...Else structure to display a message to the user based on the IsDataValid Boolean value. Listing 18.12 shows these two procedures: Listing 18.12 CH7_3.HTMThe ClearAll and NotifyUser Procedures of the Client-Side Data Validation Page

<script language="VBS"> <!-'================================================== ' Data Validation routines '================================================== 'clears all entry fields Sub ClearAll txtBoxName.Value = "" txtBoxAddr1.Value = "" txtBoxAddr2.Value = "" txtBoxCity.Value = "" txtBoxState.Value = ""

txtBoxZip.Value = "" txtBoxPhone.Value = "" txtBoxFax.Value = "" sprlbl5.Caption ="" End Sub 'display status message to user Sub NotifyUser If IsValidData then sprlbl5.Caption = "Thank You for Your Patience" Else sprlbl5.Caption = MyErrorNotes End If End Sub The CheckAll() Procedure The CheckAll() function utilizes several If...Then structures to determine whether their respective text fields contain required data. In this example program, I only checked certain fields to make sure that they contain data. The exception to this is the Phone and Fax validation routines. They are If... Then...Else structures that call another function that actually checks each character for proper type and format. The CheckAll() function starts by assuming success and sets the IsDataValid variable to True. If any of the validation routines fails, they will set this value to False. They also set the ErrorNotes variable to contain their particular error message. Listing 18.13 shows the CheckAll() procedure's code. Listing 18.13 CH7_3.HTMThe CheckAll() Function of the Client-Side Data Validation Page

'checks all fields for valid data Function CheckAll 'assume valid data to begin with 'and clear the ErrorNotes. Dim MyCheck IsValidData = True MyErrorNotes="" 'there are a series of If..then statements 'that check for valid data in each field If Len(txtBoxName.Value) < 1 then IsValidData = False MyErrorNotes ="Name Field is requiured data. " End If If Len(txtBoxAddr1.Value) < 1 then IsValidData = False

MyErrorNotes = "Address1 Field is required data. " End If If Len(txtBoxCity.Value) < 1 then IsValidData = False MyErrorNotes = "City Field is required data. " & Newline End If If Len(txtBoxState.Value) <> 2 then IsValidData = False MyErrorNotes = "State Abbreviation Field is requiured data. " End If If Len(txtBoxZip.Value) < 5 or _ Len(txtBoxZip.Value) >10 then IsValidData = False MyErrorNotes = "Postal Code #####-#### Field is requiured data. " End If 'Phone & Fax are not required fields so 'validate them only if there if data is present If len(txtBoxPhone.Value) > 0 then MyCheck = IsUSPhone(txtBoxPhone.Value) If Len(MyCheck) > 0 then txtBoxPhone.Value = MyCheck Else IsValidData = False MyErrorNotes = "Phone Number Is Incomplete or wrong Format" End If End If If len(txtBoxFax.Value) > 0 then MyCheck = IsUSPhone(txtBoxFax.Value) If Len(MyCheck) > 0 then txtBoxFax.Value = MyCheck Else IsValidData = False MyErrorNotes = "Fax Number Is Incomplete or wrong Format" End If End If CheckAll = IsValidData End Function You'll notice that the Phone and Fax validation routines differ from the other validation routines in that there is an If...Then...Else nested within the If...Then structure. The outer conditional first checks to see if there is any data in the fields to begin with. Since in this application the Phone and Fax numbers are not required fields, The outer conditional skips validation if there is no data in the Phone or Fax fields. But if there is data, then the outer conditionals will call the IsUSPhone() function to ensure that the data entered is both valid and properly formatted.

The IsUSPhone() Procedure The IsUSPhone() function validates only for North American phone standards, including the area code. Again in the case of the CheckAll() function, it is not concerned with how IsUSPhone() does its job, it only is concerned with getting a string with data back. If the string returned is empty, then it assumes an error condition and sets IsValidData to False. If it does get a non-empty string back it replaces the string in the Phone or Fax text control and continues on. You may wonder what happens if the phone number is incomplete. The CheckAll() function is unconcerned with the format and flags correct but incomplete data as valid data. Well, I had to break the encapsulation rules here. Visual Basic Script does not support passing data arguments by reference; thus, I was not able to pass a modified argument back to the calling routine. The compromise was to use the function value itself to pass back a string if the data was valid in format and content. The problem is that I couldn't pass back the fact that the data was incomplete if it was incomplete. The answer was to make IsDataValid global and change it's value in IsUSPhone() if the data was incomplete. Had I been able to pass the string back in a ByRef argument, I could have used the IsUSPhone() return value as a Boolean True or False value, thus indicating incomplete or invalid data by that value. Listing 18.14 shows the code for the IsUSPhone() procedure. Listing 18.14 CH7_3.HTMThe IsUSPhone() Procedure of the Client-Side Data Validation Page

'this function formats and validates phone 'numbers in the US format. Function IsUSPhone(MyText) Dim Icount Dim MyChar Dim MyBuffer 'iterate through all the characters 'in MyText checking for format and type For Icount = 0 to Len(MyText)-1 MyChar = Mid(MyText,Icount,1) If Icount = 0 then If MyChar <> "(" then If IsNumeric(MyChar) then MyBuffer = "(" & MyChar Else IsUSPhone = "" Exit Function End If Else

MyBuffer = MyChar End if ElseIf (Icount = 2 and Mid(MyText,0,1) <> "(") _ Or (Icount = 4 and Mid(MyText,0,1) = "(") Then If MyChar <> ")" then If IsNumeric(MyChar) then MyBuffer = MyBuffer & MyChar & ") " Else IsUSPhone = "" Exit Function End If Else MyBuffer = MyBuffer & MyChar End if ElseIf (Mid(MyText,0,1) = "(" and Icount = 9 and MyChar <> "-") Or _ (Mid(MyText,0,1) <> "(" and Icount = 6 ) then If IsNumeric(MyChar) then MyBuffer = MyBuffer & "-" & MyChar Else IsUSPhone = "" Alert "3" & MyChar Exit Function End If ElseIf (Mid(MyText,0,1) = "(" and Icount = 9 and MyChar = "-") Then MyBuffer = MyBuffer & MyChar ElseIf (Mid(MyText,0,1) = "(" And Icount > 13) _ Or (Mid(MyText,0,1) <> "(" And Icount > 9) Then 'Exit For ElseIf IsNumeric(MyChar) or MyChar = " " Then MyBuffer = MyBuffer & MyChar Else IsUSPhone = "" Exit Function End If MyChar="" Next If Len(MyBuffer) < 13 then IsValidData = False Else End If IsUSPhone = MyBuffer End Function --> </script>

</body> </html> The main feature of this function is the For...Next looping structure that iterates through each character in the MyText value that is passed to it. It checks each character for proper format position and value. If it finds one of the (, ), or - characters missing, it inserts them where they belong and continues on. If it finds characters that are not part of the phone number format or are not numeric where they should be or some other condition it cannot handle, the loop exits the function, returning an empty string. If it does complete its iteration through the string without incident, then the loop checks for proper length, chopping off any extra characters it finds. This validation routine is not the best algorithm I have ever written, but it does give you a strong indication of the possibilities using Visual Basic Script. Refer to Figure 18.6 for an illustration of the client-side validation example. To add a little more functionality to this example I added a Timer control that checks the Phone and Fax entries to see if they are changed and if they are to run the IsUSPhone procedure to format them. Initially I would have thought that the changes in the text would be immediately evaluated, formatting the text as you typed. But it seems that the text is not available until after you leave the text box either by tabbing or clicking somewhere else on the page. Anyway, the code in Listing 18.15 adds the ability to validate the data as the user moves to another area, giving a more immediate response to data entry. Enter this code immediately after the <Body> tag on your HTML document. Listing 18.11 CH7_4CSV.HTMAdding the Timer Control <object classid="{59CCB4A0-727D-11CF-AC36-00AA00A47DD2}" id=timer1 align=middle > <param name="TimeOut" value="100"> <param name="enable" value="1"> </object> In the second Visual Basic Script module add the Timer event code shown in Listing 18.16. Listing 18.16 CH7_4CSD.HTMTimer Event Code for Immediate Data Validation 'validate as we leave the text box sub timer1_time MyCheck = IsUSPhone(txtBoxPhone.Value) If Len(MyCheck) > 0 then txtBoxPhone.Value = MyCheck Else IsValidData = False MyErrorNotes = "Fax Number Is Incomplete or wrong Format" End If

MyCheck = IsUSPhone(txtBoxFax.Value) If Len(MyCheck) > 0 then txtBoxFax.Value = MyCheck Else IsValidData = False MyErrorNotes = "Fax Number Is Incomplete or wrong Format" End If End Sub Once added, the Timer calls the validation routines for the Phone and Fax entries. The validation effects won't happen until you leave the field you are editing. I hope this chapter has given you a fair idea of what is possible in Visual Basic Script as well as an idea of what the limitations are as well.

From Here...
The programming structures presented in this chapter are nothing new to most intermediate programmers. They are a set of interlocking building blocks used in constructing programs. In later chapters you will see more complex and advanced application of these structures. VBScript continues to evolve even as I write this chapter and you may find some things altered. The release that I am working with added the Select...Case structure only the week before editing this chapter. The ByRef keyword was removed from the documentation at the same time. The best approach you can take is to experiment to see what works and what doesn't at the time you are working with VBScript. The ActiveX Control Pad makes an excellant tool for writing structured VBScript code and Chapter 3 takes you through its capabilities.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 18 - VBScript Event Programming


by Ron Schwarz

In this chapter
q q q q q q q q

q q

Events Learn what events are, and how they relate to other aspects of VBScript programming. Event Sources Find out which objects generate events, and what events they generate. Comparing Events Examine differences between similar events generated by related elements. Managing Events with the ActiveX Control Pad See how to use the Script Wizard component of the ActiveX Control Pad to easily manage event code. Using Events Create event-driven scripts using the information learned in this chapter.

VBScript programming consists largely of designing layouts, writing code that deals with properties, events, and methods. This chapter covers events. It contains a short tutorial on event programming, and a rundown on handling events generated by the Internet Explorer, HTML Intrinsic controls, and a few of the literally thousands of available ActiveX custom controls.

Event Programming
An event-driven environment, such as Microsoft Windows, allows the user to interact with applications in a manner entirely different from older procedural systems, which tended to force the user to respond to the software in a highly regimented action/reaction sequence. When a user clicks or moves the mouse, strikes a key, or opens a document, events are generated. By intercepting these events, and associating program code with them, applications provide a flexible, responsive interface, without the constraints imposed by old style procedural programs.

VBScript provides a mechanism for dealing with events as they occur. If you're familiar with Visual Basic, you have a head start on coping with VBS event issues. However, there are some significant differences in how things are handled in VBS. Thanks to the differences between Web pages and VB applications, event handling is a bit more complex with VBS. Fortunately, the ActiveX Control Pad helps ease the bumps, and automates much of the process of declaring and installing objects. In VB, you have the luxury of the code window and an editor that automatically keeps track of all possible events for all objects in your project. It also automatically creates perfect event procedure headers. When working with VBS, however, you have two choices: you can either work in Notepad or a similar simple editor (This means you have to know which objects generate which events, and how to manually create the appropriate headers for each, as required), or, you can work in the ActiveX Control Pad. For popping in and out of simple scripts, you may find Notepad sufficient, but for any significant development, you'll definitely want to learn how to use the ActiveX Control Pad. In addition to making it easier to manage complex web pages, it also provides a visual, interactive "VB-like" IDE (Integrated Development Environment) which facilitates the creation and management of HTML Layout Pages. The HTML Layout Pages are a very close approximation of "real" VB programming, right down to the toolbox, mouse-driven control placement and sizing, and Properties window. About the only thing missing is the debugging features.

See Chapters 3-5, which cover the ActiveX Control Pad in detail.

VBScript Events
VBS events can originate in the Internet Explorer, HTML Intrinsic controls, or ActiveX custom controls. ActiveX custom control event handling is closest to VB event handlingthis is no surprise since ActiveX controls are also used in VB. HTML Intrinsic controls are not all that different in usage; the main differences are in declaration syntax and event and property naming conventions. Listing 18.1 gives you a typical VBScript event handler. If you've used VB before, you'll note that it's virtually identical to a VB event handle; the only exceptions are the HTML tags that mark the beginning and end of the script, and the event name (OnClick, rather than Click). You can, by the way, have many separate routines in a single script. Listing 18.1 Typical Event Header

<SCRIPT LANGUAGE="VBScript"> Sub cmdCalculate_OnClick Total = LastMonth + Current End Sub </SCRIPT> You may also want to experiment with alternative control header styles such as the FOR syntax, shown in Listing 18.2. Listing 18.2 FOR Style Event Header <SCRIPT LANGUAGE="VBScript" FOR="cmdEvent" EVENT="OnClick"> Window.Status="Clicked!" txtStatus.Value = link1.href </SCRIPT> This syntax does away with VB-style event sub-procedures. You may notice the absence of either a Sub or End Sub line in the preceding script block. The code is VBS, but it's not part of a VBS procedureit is invoked when the object declared with the FOR parameter fires the event described in the EVENT parameter.

Internet Explorer Events


The Internet Explorer Object Model consists of a hierarchy of objects, most of which provide events (see fig. 18.1). This chapter does not cover aspects of objects that do not pertain to events. These topics are covered in "The Internet Explorer Object Model," in Chapter 10, "Embedding Internet Explorer into your Application." (Objects that provide no events are mentioned here in passing, to allow continuity of the Object Model, so you will have a good perspective on where events fit into the general scope of the hierarchy.) The relationships between the different levels of the Object Model (to the extent that they involve event handling issues) are discussed in the following sections. FIG. 18.1 Internet Explorer Object Model Window Object Events The Window object has two events: OnLoad, and OnUnload. OnLoad fires when a page is loaded. Inline code (VBS code that is contained within <Script> blocks but outside any procedures) executes before the OnLoad event occurs, and may be a pseudo-event mimicking the Initialize event in VB. All inline code is affected, regardless of position. If multiple blocks of inline code exist in different locations within the page, they are executed first to last. After the last inline block finishes executing, the OnLoad event fires, and any associated code executes.

There is a significant distinction between inline code and OnLoad event code. Operations that change the content on the page, such as document.write method invocations, can only be performed with inline code since this code is executed as the page is being loaded, whereas the OnLoad event fires after the page has been loaded and formatted. The OnUnload event is the counterpart to the OnLoad event. It is fired when the page is about to be unloaded. Frame Object The Frame object is an array of windows. It is covered in Chapter 2, "Review of HTML." History Object The History object exposes the Internet Explorer's History list (previous locations). It has no events. Navigator Object The Navigator object contains information about the browser, similar to the App object in Visual Basic. It has no events. Location Object The Location object has no events. However, changing its properties results in events being fired by the Window object as pages are unloaded and loaded. Script Object The Script object is a collection of all scripts in the page. Because scripts are contained in the object hierarchy, they can be called from different windows by prefacing them with the name of the window that contains them, similarly to prefacing a procedure with a form or module name in VB. They expose no events. Document Object The Document object provides no events. However, it serves as container for other objects that do fire events. (The Link, Anchor, and Form objects are contained in the Document object, and are described in the following sections.) Form Object The Form object has one event: OnSubmit. When a form is submitted, the contents of the controls in the form are sent to the server. Immediately prior to sending them, the OnSubmit event fires, and be used to perform whatever validation is required, and cancel the submission if required. Unfortunately,

at the time this book is going to press, OnSubmit is not yet functional using the pre-release tools available. This should be resolved by the time Internet Explorer 3.0 and VBScript are released. Link Object The Link object contains a collection of all link-type anchors on the page. It provides MouseMove, OnMouseOver, and OnClick events for each link.The example in Listing 18.3 (LinkEvent.htm on the CD), demonstrates how to trap the MouseMove and OnClick Link events. Listing 18.1 LINKEVENTS.HTMLink Events Example <A HREF="http://www.microsoft.com" NAME="MSLink">Microsoft Main Web Site</A> <p> <Input Type=Text ID="txtStatus" Size=35> <OBJECT ID="tmrStoppedMoving" WIDTH=39 HEIGHT=39 CLASSID="CLSID:59CCB4A0-727D-11CF-AC36-00AA00A47DD2"> <PARAM NAME="Interval" VALUE="100"> </OBJECT> <SCRIPT LANGUAGE="VBScript"> Sub MSLink_OnClick Confirmation=MsgBox("Really go to MS?", 4) If Confirmation=7 then '7 = "No" button pressed MsgBox "That's unfortunate, since the Link can't be cancelled!" end if End Sub Sub MSLink_MouseMove(Button, Shift, X, Y) txtStatus.Value="You ARE moving over a link!" 'Update the display tmrStoppedMoving.Interval=0 'Stop the clock tmrStoppedMoving.Interval=250 'Start timing, 250 msec. End Sub Sub tmrStoppedMoving_Timer txtStatus.Value="You're NOT moving over a link!" 'Time ran out, update display End Sub </SCRIPT> The LinkEvents example contains one Link, one Text control, one Timer, and a script. The Link is given a NAME property (MSLink), so that its events can be trapped by the event routines in the script. The MSLink_OnClick event procedure will execute if the on-screen link is clicked. When it executes, it first displays a messagebox asking for confirmation. If you click the "No" button, you'll see another messagebox informing you that the Link can't be cancelled. The browser will then take you to the URL contained in the link. C'est la vie. (This event is actually usefulfor cases where you need to

perform "cleanup" code before leaving for the new URL.) The MSLink_MouseMove event fires repeatedly as the mouse travels over the link. Three things are done here in this example: the Value property of the Text control is updated to reflect the fact that the mouse is moving over the Link, the Interval property of the Timer control is set to 0 to disable it, and then immediately reset to 250. By setting the Interval to 0 and then 250, the Timer is stopped, and another 250 millisecond period begins; as long as the mouse keeps moving over the Link, the Timer will be continuously reset, and never fire its event. If the mouse stops moving, or moves off the Link, the MouseMove event will stop firing, and the Timer will time out, and fire its Timer event. At that point, the code in the tmrStoppedMoving_Timer event procedure will execute.

As this book goes to press, the OnMouseOver event is documented, but not implemented. If implemented, it will provide a simplified form of the MouseMove eventit will be invoked the same way, but without any parameters.

Listing 18.2 IMGAST.HTMImageMap Assistant Example <HTML> <TITLE>ImageMap Assistant</TITLE> <HEAD> <CENTER><H1>VBScript ImageMap Assistant</H1></CENTER> <SCRIPT LANGUAGE="VBScript"> Dim ClickCount Dim HotspotCoords Sub picXY_MouseMove(Shift, Button, X, Y) txtX.Value = X txtY.Value = Y End Sub Sub picXY_OnClick If ClickCount = 0 Then ClickCount = 1 HotspotCoords = txtX.Value & ", " & txtY.Value & ", " Else ClickCount = 0

HotspotCoords = HotspotCoords & txtX.Value & ", " & _ txtY.Value End If txtHotspot.Value = HotspotCoords End Sub </SCRIPT> </HEAD> <BODY> <p> <center> <a id="picXY" href=""><img src="events.bmp"></a> <p> CurrentX: <input type="text" name="txtX" size=10> CurrentY: <input type="text" name="txtY" size=10> <p> Hotspot: <input type="text" name="txtHotspot" size=20> </center> Position the mouse at the upper left corner of your desired hotspot, and click. Then, move to the lower right corner of the hotspot, and click again. The "Hotspot:" textbox will contain your X, Y, X1, Y1 coordinates. </BODY> </HTML> The ImageMap Assistant is a useful VBS application. Although it only uses 16 lines of VBS code, it solves a problem that vexes anyone creating image mapshow to determine coordinates for hotspots.

To use the ImageMap Assistant with your bitmaps, find the line <a id="picXY" href=""><img src="events.bmp"></a> Then, replace events.bmp with the name of your actual bitmap.

The MouseMove event is repeatedly fired as the mouse is moved over the link. The ImageMap Assistant example uses this event to periodically update the CurrentX and CurrentY textboxes. The MouseMove event passes four parameters: Shift, Button, X, and Y. The Shift parameter returns a

value indicating the state of the Shift, Ctrl, and Alt keys, according to the following table (See hard copy for the key icons): Key Shift Parameter Value Shift Ctrl Alt 1 2 4

You can test for a condition of multiple shift keys by "ANDing" the values. The following example code evaluates whether or not the Shift and Ctrl keys are pressed at the time the event occurs. (If none of the Shift keys are pressed, the Shift parameter returns 0.)

See Chapter 16, "VBScript Operators," for information on AND and other logical operators.

If ((Shift And 1) > 0) And ((Shift And 2) > 0) Then End If The Button parameter is similar in behavior to the Shift parameter; it returns a value indicating which, if any, mouse buttons were pressed when the event occurred. You can test for multiple button press conditions using the same formula used with the MouseMove event, substituting the Button parameter for the Shift parameter. The X and Y parameters return the position of the mouse pointer relative to the upper-left corner of the object. In the ImageMap Assistant example (this code fragment from IMGAST.HTM on the CD is shown in Listing 18.5), they are used to populate the CurrentX and CurrentY textboxes and to create the coordinate list. (The coordinate list is the list of the four numbersstarting XY and ending XYcontained in the txtHotspot Text control.) The OnClick event occurs when the user clicks the left mouse button while the mouse pointer is over the object. It's a simple event, but is probably used more than all others combined. In the ImageMap Assistant, it's used to update the hotspot coordinates list.

Listing 18.5 IMGAST.HTMOnClick Event Code Sub picXY_OnClick If ClickCount = 0 Then ClickCount = 1 HotspotCoords = txtX.Value & ", " & txtY.Value & ", " Else ClickCount = 0 HotspotCoords = HotspotCoords & txtX.Value & ", " & txtY.Value End If txtHotspot.Value = HotspotCoords End Sub In this event Sub, you check to see if this is the first time the mouse is clicked. If it is, you replace anything in the hotspot coordinates textbox (txtHotspot) with the current X and Y values. Otherwise, you append them to the existing contents. After two clicks you have four values, which can be copied to the Clipboard and pasted into a VBS script. (You need to write additional VBS code to deal with the lists of hotspot coordinates, but that's the easy partthe ImageMap Assistant code eliminates the tedium of trial and error guesswork when creating image maps.) Figure 18.2 shows how the ImageMap Assistant will look when you load it into Internet Explorer. FIG. 18.2 ImageMap Assistant The ImageMap Assistant will be invaluable when you're creating hotspots in imagemaps. For more information on imagemap issues, check out Chapter 11, "Designing VBScript Applications." Anchor Object The Anchor Object has no events. It's mentioned here in passing, since it's part of the Object Model. For full coverage of the Object Model, see "The Internet Explorer Object Model," in Chapter 10, "Embedding Internet Explorer into Your Application." Form Object The Form Object contains one event: OnSubmit. The OnSubmit event fires when a Form (an HTML form, not to be confused with a VB form) is submitted. There are two ways to submit a formthe form's Submit method, and the use of a Submit HTML Intrinsic control. (As this book goes to press, the OnSubmit method is documented insofar as it is known that it will be available in the final release of IE 3.0, however, it is not yet implemented in the pre-release version, nor is VBScript syntax available.)

Element Object The Element Object is an array of all controlsHTML and OBJECT (such as ActiveX)on a page. It's similar in concept to the Control Collection in Visual Basic. Because it's really just a series of pointers to "real" objects; it has no events of its own. For a full discussion of the Element Object, see "The Internet Explorer Object Model," in Chapter 10, "Embedding Internet Explorer into your Application."

Control Events
VBS is able to detect events fired by the Intrinsic HTML and ActiveX controls. The main differences between using HTML controls and ActiveX controls involve declaration conventions and event names. (Control declaration issues are covered in other chapters.)

Hammers, Nails, and Platforms Apart from usage differences, you may notice that HTML controls have a dearth of events when compared to most ActiveX controls. HTML, even when VBS-enabled, is not a fullfledged program development platform. VBS scripts are not complete applications. Automating Web pages is not the same as creating Visual Basic applications. This is not by any means derogatory toward VBS. It's just a different animal. The axiom that says, "To a man with a hammer, everything looks like a nail," is something you need to keep in mind when developing script-enabled Web pages. The ability to create HTML Layout Pages by using the ActiveX Control Pad does indeed make it possible to create real programs with VBS. Still, trying to do some things, such as accessing INI files or the registry, and using API calls require severe work-arounds in VBS. So, sooner or later, you'll find a situation where what you really need is a comprehensive solution best provided by a Visual Basic application. Ideally, you'll make that discovery before you commit massive amounts of time and/or money developing Web pages for the project. And, there will be times when you'll experience the reciprocal of this principlea simple Web page, brought to life with some concise, effective VBS code, is a life-saver. The moral: Use the appropriate tool for each job.

If you use VB, you are familiar with the Click event; with HTML controls, it's the OnClick event.

Similar differences with other event names are detailed in the following sections. Button Control Events The Button control has one event: OnClick. This is functionally identical to the Click event in VB. When the user clicks the button, the event fires, and any associated event code is executed. The following example demonstrates use of the OnClick event with a Button control. Sub cmdCalculate_OnClick Total = LastMonth + Current End Sub Checkbox Control Events Like the Button control, the Checkbox control also has OnClick as its sole event. Checkboxes, like option buttons (called radio controls in HTML-speak), are frequently used without requirements for active processing at click-time. In many, if not most, cases, they are checked as the user requires, and when ready to proceed, a button is clicked telling the application to process the controls. At that point, all options are parsed and whatever action is required is taken. However, there are also many situations in which you may need to perform processing when the user clicks an option. For instance, you may have mutually-exclusive or interlocking combinations of options. By testing at click-time, you can deal with input dynamically rather than all at once in a type of "batch mode." Listing 18.8 (available on the CD as CHKEVENTS.HTM) demonstrates one such hypothetical example.

Listing 18.8 CHKEVENTS.HTMCheckbox Events Example <HTML> <HEAD> <TITLE>VBScript Events</TITLE> <SCRIPT LANGUAGE="VBS"> Sub DoAll If chkAll.Checked Then 'If the "All" box is checked chkTest1.Checked = True chkTest2.Checked = True chkTest3.Checked = True End If End Sub

</SCRIPT> </HEAD> <body> <INPUT TYPE=CheckBox <INPUT TYPE=CheckBox <INPUT TYPE=CheckBox <INPUT TYPE=CheckBox </body> </HTML>

NAME="chkTest1" size=10> Oranges<p> NAME="chkTest2" size=10> Peaches<p> NAME="chkTest3" size=10> Pears<p> NAME="chkAll" size=10 OnClick="DoAll">All

Listing 18.8 demonstrates use of the CheckBox control's OnClick event. In this example, the user sees a list of four items, which can be selected in any combination. If the last item (All) is clicked, the DoAll routine in the VBS script checks all of the options. The declaration for the chkAll HTML CheckBox control contains an OnClick="DoAll" clause. This causes the DoAll Sub procedure to replace the default (chkAll_OnClick, which is not used) event handler. This syntax can be useful when you want to have several controls use the same event handler. The DoAll routine first tests whether or not the chkAll CheckBox is checked. If it is checked, the routine proceeds to check all three of the other CheckBoxes. Password Control Events The Password Control is a specialized form of the Text control. It's used when you want the user to enter text without having the characters entered echo on screen. When a character is typed into a Password control, an asterisk ("*") is displayed. The Password control has OnFocus and OnBlur events, like the Text control, but does not have OnChange or OnSelect events. For usage of the OnFocus and OnBlur events, see "Text and TextArea Control Events" earlier in this chapter.

At the time of this writing, the OnFocus and OnBlur events are documented, but not implemented for the Password control.

Radio Control Events Radio Controls (hereinafter referred to by their "VB name" of OptionButtons), have one event: OnClick. Generally, you won't need to trap this event, as OptionButtons tend to be used for the purpose of determining one of a number of fixed selections. However, there are situations in which

you may want to perform an action at the time a button is clicked. One example would be a quiz, where you want the victim (er, "student") to be unable to test the answer unless an answer was first selected. To accomplish this, it's necessary to be able to tell whether or not an OptionButton has been clicked. The example in Listing 18.9 (OptionEvents.htm on the CD) demonstrates such a situation.

Listing 18.3 OPTIONEVENTS.HTMOptionButton Event Example <HTML> <HEAD> <TITLE>VBScript OptionButton Events</TITLE> </HEAD> <SCRIPT LANGUAGE="VBScript"> Dim OkToTest, c Sub Window_OnLoad 'Can't set controls before page created optNum.Item(0).Value = False 'Clear default selection txtStatus.Value = "Your answer please!" End Sub Sub CanTest OkToTest = True For c = 0 To 2 'Walk through all buttons If optNum.Item(c).Checked Then 'If we've found the selection Exit For 'Answer found, stored in c End If Next txtStatus.Value = "Answer " & c + 1 & " Selected" 'Add 1 because End Sub 'buttons start at 0 Sub cmdTest_OnClick If OkToTest Then FindAns Else txtStatus.Value = "Must Select an Answer!" End If End Sub Sub FindAns Select Case c 'Test if it's the right answer Case 0, 2 txtStatus.Value = "Wrong!" Case 1 txtStatus.Value = "Correct!" End Select End Sub

</SCRIPT> <BODY> One Plus One Equals:<P><P> <INPUT TYPE="Radio" NAME="optNum" size=10 OnClick="CanTest">One<P> <INPUT TYPE="Radio" NAME="optNum" size=10 OnClick="CanTest">Two<P> <INPUT TYPE="Radio" NAME="optNum" size=10 OnClick="CanTest">Three<P><P> <INPUT TYPE="Button" NAME="cmdTest" VALUE="Test"><P> <INPUT TYPE=TEXT NAME="txtStatus" size=20> </BODY> </HTML> The example in Listing 18.9 uses four controlsthree OptionButtons, a CommandButton, and Text: <INPUT TYPE="Radio" NAME="optNum" size=10 OnClick="CanTest">One<P> <INPUT TYPE="Radio" NAME="optNum" size=10 OnClick="CanTest">Two<P> <INPUT TYPE="Radio" NAME="optNum" size=10 OnClick="CanTest">Three<P><P> <INPUT TYPE="Button" NAME="cmdTest" VALUE="Test"><P> <INPUT TYPE=TEXT NAME="txtStatus" size=20> The OptionButtons are all given the same name (optNum), which is what associates them as a group. In this example, they all use the same event handler (CanTest) although you can use different handlers for each of them if you require. (You can also use the default handlers, which for this example would have been optNum_OnClick.) The CommandButton is named cmdTest, and the Text control is named txtStatus. The script begins with a declaration of two Public variables: Dim OkToTest, c It's necessary to make these variables Public because they're used in more than one procedure. By declaring them outside of any procedure, they're automatically available to all procedures. The first procedure is the Window_OnLoad event handler: Sub Window_OnLoad 'Can't set controls before page created optNum.Item(0).Value = False 'Clear default selection

txtStatus.Value = "Your answer please!" End Sub Before you can set properties of a control, the control has to be loaded. And, if you want to set control properties during the initialization phase (such as, only once, when the page loads) you'll have to do so in the Window_OnLoad event, since if you execute them outside of any procedure, they'll be executed during the parse phase, before any controls are created. To address a specific OptionButton in code, you need to use the Item property. The code in the Window_OnLoad event sets the Value property of the first OptionButton to False. Because OptionButtons begin with 0, that's the one that's set here. This code clears the first button. (By default, the first button in a group is selected, and since this example needs to have none selected, the first one has to be explicitly cleared.) Before the procedure ends, it places "Your answer please!" into the Text control, so that the user will know to click one of the OptionButtons. The CanTest event serves as the event handler for the OptionButtons: Sub CanTest OkToTest = True For c = 0 To 2 'Walk through all buttons If optNum.Item(c).Checked Then 'If we've found the selection Exit For 'Answer found, stored in c End If Next txtStatus.Value = "Answer " & c + 1 & " Selected" 'Add 1 because buttons start at 0 End Sub The first thing this routine does is set the OkToTest variable to True. This variable is used in the cmdTest_OnClick event handler to determine whether or not an answer has been provided. (The CanTest procedure isn't called unless an OptionButton has been clicked. Because an OptionButton has been clicked, it's "OkToTest" the answer when the Test button is clicked.)

For information on For/Next loops, see Chapter 17, "VBScript Control of Flow and Error Handling." For more information on OptionButton properties, see Chapter 20, "VBScript Forms, Controls, and Managing Transactions."

After setting the OkToTest variable, a For...Next loop counts through the OptionButtons, looking for the one that was selected. Because OptionButtons start with an Item of 0, the loop counts from 0 to 2. When it finds the selected OptionButton, it executes an Exit For statement to escape the loop. Because the loop counter (c) reflects the current OptionButton at the time it's found, it stores its number. For instance, if the second OptionButton (.Item(1)) has its .Checked property set to True, then the value of c will be 1. After the loop finds the number of the selected OptionButton, the status string (the .Value property of txtStatus) is set to a string composed of the word "Answer," the number of the OptionButton, and the word "Selected." Because OptionButtons start at 0, but answers on a quiz start at 1, the number in the string is offset by one (by adding c + 1). After an answer is selected, the user will have to click the Test button to see if it's correct. The OnClick event for the cmdTest button directs the script to the FindAns routine to determine if the right answer was provided: Sub cmdTest_OnClick If OkToTest Then FindAns Else txtStatus.Value = "Must Select an Answer!" End If End Sub Before handing control over to the FindAns routine, cmdTest_OnClick checks the value of OkToTest. (This is the variable that is only set if the user first clicks an OptionButton.) If it's indeed ok to test, FindAns is called. If not, txtStatus is loaded with a warning to select an answer. The FindAns routine does the actual testing: Sub FindAns Select Case c 'Test if it's the right answer

Case 0, 2 txtStatus.Value = "Wrong!" Case 1 txtStatus.Value = "Correct!" End Select End Sub A Select Case block tests the value of c against 0 and 2 (the incorrect answers), and 1 (the correct answer), and displays the appropriate message in the status Text control. Reset Control Events The Reset control is a special type of button control. When it's clicked, it clears the contents of the other controls. At the time this book goes to press, it has one event implemented: the OnClick event. (An OnFocus event is documented, but not working.) Submit Control Events The Submit control has one event: OnSubmit, which is covered under "Form Object" earlier in this chapter. Text and TextArea Control Events The Text and TextArea controls have OnFocus and OnBlur events. These correspond to GotFocus and LostFocus events in VB. Because the TextArea control can be considered a functional equivalent of a VB TextBox control with a Multiline property set to True, we examine the two of them together here.

At the time of this writing, the OnChange and OnSelect events are documented, but not implemented for the Text, TextArea, and Password controls. The OnChange event will fire when the contents of the control change, and the OnSelect event will fire when text is selected within the control.

Listing 18.8 Text and TextArea Events Example Sub txaTest_OnFocus txtTest.Value ="OnFocus" End Sub Sub txaTest_OnBlur txtTest.Value ="OnBlur" End Sub The code in Listing 18.7 updates the display in a Text control (txtTest) whenever the OnFocus or OnBlur events occur in a TextArea control (txaTest).

ActiveX Control Event Issues


In many situations, the HTML Intrinsic controls provide all the interactivity your applications require. For certain situations, however, you need features they do not provide. ActiveX controls provide specialized functionality that is not available via the Intrinsic controls. When an Intrinsic control does the job, use it. The Intrinsic controls are general-purpose input and display controls; ActiveX controls are specialized controls. Each ActiveX control is unique, and is created with a specific purpose in mind. Many of them are quite complex, and require quite a bit of detailed study to use effectivelysome of them are essentially major applications disguised as "tools" that can be embedded in a container such as an HTML Layout Web page. Their power and flexibility aside, they require no less attention to detail and study than does a standalone program of a similar nature. Those developers who choose to learn the details of their tools are able to leverage them to great effect. ActiveX controls are supplied by numerous vendors. Remember, the main usage distinction between ActiveX controls and HTML Intrinsic controls deal with declaration and naming of properties and events; the actual use in your script blocks is the same (in regards to event handling). The information provided earlier in this chapter for HTML controls also equally applies to ActiveX controls.

From Here...
An understanding of event handling is necessary to make real use of VBS. The material presented in this chapter provides you with the mechanics involved in using event routines. The information presented in Part 4 of this book presumes an understanding of the material presented here, and goes on to teach you how to use that knowledge to create powerful script-enabled Internet applications.
q q

See Chapter 2, "Review of HTML," for general HTML programming information. See Chapter 4, "Creating a Standard HTML Page," for more coverage of HTML control programming issues. See Chapter 9, "An Introduction to Distributed Objects," for cutting edge information on controls.

See Chapter 11, "Designing VBScript Applications," for information on putting this chapter's material to work. See Chapter 20, "VBScript Forms, Controls, and Managing Transactions," which covers data validation and transactions. Que's Special Edition Using HTML.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 19 - VBScript Procedures

q q

q q q q q q q q q

Constructing procedures Why break up your code into function and subroutine procedures? Heres the scoop on how to create them and why. Calling procedures Look here to learn how to use those procedures in your scripts. Exiting procedures Things to consider when terminating a procedure. Procedure parameters Passing information between procedures, the how and why of procedure parameters. Strategies for good code design Discusses how to break up your VBScripts into managable sections. Applying structured techniques

In this chapter, we discuss the processes involved in creating procedures in Visual Basic Script, along with different strategies in arranging those procedures. In an earlier chapter, I discussed the concept of limiting the scope of data and encapsulating functionality as much as possible. Here, I take the discussion a little further by developing strategies in the decisions that involve making procedures in what constitutes a well designed routine hierarchy. When you are finished with this chapter, you will have learned some new approaches to application design and perhaps even been stimulated to develop these ideas even further.

Constructing Procedures
If you are coming entirely from an HTML background with little experience in a structured programming environment, like Visual Basic Script, this is the chapter for you. A procedure in Visual Basic Script is a structure with a single entry point and one or more exit points containing a series of statements that perform a particular task. Procedures are called by other lines of code to perform a given task and return the program flow back to the line that The procedure was called from. In most cases, procedures can look just like keywords and intrinsic functions when used and, in fact, work the same way. The process of creating a procedure starts with identifying the reasons for a procedure. A procedures

primary purpose is to reduce the complexity of your program. Procedures should hide the detail information so you dont have think about those details when you are actually using those procedures. Other reasons for a procedure include code reuse, maintainability, and accuracy. You decide how the procedure will actually go about performing the task assigned to it, write the code for that procedure, and thoroughly test it for accuracy and volatility. The accuracy of the results derived from your procedure should be checked using the extreme ranges of your expected data. Find out what breaks your procedure, and then devise ways to prevent that procedure from being broken.

The following are good candidates for a procedure:


r r r r

A process that involves multiple lines of code A process that can be reused by other areas A process subject to later modification A process that includes complex logic

Declaring Procedures
In Visual Basic Script, you declare a procedure by declaring it as a Sub or Function, and provide a unique name for the procedure, as well as any arguments that should be included. The basic syntax for declaring a procedure is: [Private|Public] Sub|Function name (arg1, arg2,) .procedure code End [Sub|Function} The [Private|Public] arguments are scope arguments. A public procedure can be seen by all procedures in all script modules. A private procedures scope is limited to the script module that it is declared in. Both arguments are optional and the default is a public procedure. The Sub|Function keywords define the type of procedure it is. Note that in Visual Basic Script there are no property procedures as in Visual Basic. The (arg1,arg2,...) portion is where you declare the arguments that are to be passed to your procedure. Here is a good place to talk about variable scope again. Global variables should be used as little as possible. It is much better programming practice to pass values to other procedures through the argument list. This way you know what data the procedure requires and what data the procedure modifies. Global variables, on the other hand, can be modified in any procedure any where in your code.

Many programmers like the convenience of global variables because they are easily accessible. Others, like myself, prefer to minimize the scope of a variable as much as possible so their purpose can be maintained and readily understood. When they are globally available you no longer have that maintainability and do not easily understand all the complexities that can be involved with that data. The End Sub or End Function statements mark the limits of the procedure.

Function Procedures
A function type procedure is a block of code that takes arguments, processes those arguments, and then returns a value as part of its call. A function can also be used as part of an expression. Functions are mostly used to process information in a specified manner and return a result on the basis of the information. A function can return any of the data sub-types supported by the variant. Also, by default, arguments passed to a function are passed by reference so that if you change the value contained in an argument those changes are available to the procedure that called it. If you do not want the function to make changes to an argument that is passed back to the calling procedure then you have to declare the argument as ByVal. In this case, the argument is passed as a value rather than a pointer to the location where the data is stored (see Listing 20.1). Listing 20.1 The Syntax for Declaring a Function Procedure [Private|Public] Function name ([arg1, arg2,...) ...Code block End Function explanation: Private|Public are optional scope declarations. The default is public. name is a string expression that identifies the subroutine arg1,arg2,.. are optional arguments passed to the subroutine code block is where you enter the code to be executed by the procedure example declaration Public Function WhatDayIsToday(DateValue) If not IsDate(DateValue) then WhatDayIsToday = Invalid Date Else Dim MyResult MyResult = WeekDay(DateValue) WhatDayIsToday = MyDayArray(MyResult) End If End function example use of function Label1.caption = WhatDayIsToday(Now) In the function example provided in Listing 20.1, you may notice there is some simple error trapping that checks to make sure the DateValue argument is, in fact, a date value. Another point you may

notice is that when reading the function you learn exactly what the function does. This is an important feature to strive for. Name your procedures and variables with names that fully describe what they do or what they contain. You may understand your code when you write it, but when you come back to maintain it in a week, month, or even a year, youll appreciate being able to instantly recognize your intended logic thanks to adequate naming conventions.

Subroutine Procedures
A Subroutine (Sub) procedure differs from a function in that it does not return a value and cannot be used as part of an expression. Like the function procedure, it is a discrete block of code that is called from another procedure, and, when it is done, immediately returns to the next operation after the line that called it. The syntax of a Sub is as shown in Listing 20.2: Listing 20.2 Syntax for Declaring a Subroutine [Private|Public] Sub name ([arg1, arg2,...]) ...code block End Sub explanation: Private|Public are optional scope declarations. The default is public. name is a string expression that identifies the subroutine arg1,arg2,... are optional arguments passed to the subroutine code block is where you enter the code to be executed by the procedure example of Sub declaration: Private Sub DisplayDay(DateValue) Label1.caption = MyDayArray(WeekDay(DateValue)) End Sub using the sub DisplayDay Now Call DisplayDay(Now) In Listing 20.2, you see two ways to invoke a subroutine. If you just use the Subs name you pass the argument without the parentheseses. If you use the Call keyword then you must surround the arguments with parenthesis. Again, you may notice that the naming convention of the Subroutine describes exactly what it does.

Calling Procedures
Calling procedures in Visual Basic Script work exactly the same as in Visual Basic. Functions are usually used as part of expressions, since they can return a value, and subroutines are used as statements. To call a function procedure, you can either use it as part of an expression or use it like a subroutine

ignoring the return value. If you use it as part of an expression, you must include the parentheses whether there are parameters to pass or not. If you do not use it as part of an expression then you must leave off the parentheses. Examples of both types of calls are given in Listing 20.3. Listing 20.3 Using a Function in an Expression CheckSpeed() is used in an expression to set a value lngRotation = CheckSpeed(txtDegrees.Value) here, CheckSpeed() is used without regard for a return value CheckSpeed txtDegrees.Value

Call
Call is an optional argument used to transfer control to a subroutine or function. When used, it requires you to wrap the argument list in parentheses. When the Call statement is used with a function, the return value is discarded.using the call statement would look like this: Call ChangeRotation().

Exiting Procedures
You may not think exiting procedures the subject of much discussion at first glance. But I have had some interesting discussions on this subject that revolve around the proper way to exit a procedure. I am a strong advocate of the single-entry, Single Exit rule that states there should only be a single point of entry in a procedure and a single point of exit. In Visual Basic, the single entry is enforced for all types of procedures. The single exit point, however, is another matter. In Visual Basic, labels and the much-maligned GoTo statement allow a programmer to easily construct procedures that follow the single exit point rule. Visual Basic Script, however, does not utilize labels or GoTo. You can still have your procedures follow the single exit point, but this involves more complex logic in certain situations. I like having procedures that follow a consistent pattern with distinct logic, exit, and error handling sections. Visual Basic Script makes this a little difficult since error handling has to be inline; and if an error cannot be rectified in your procedure logic, you must provide your error exit code immediately after the error or concoct some unique and probably convoluted logic to delay the need to exit the procedure. If there is a way to correct an error in line, there is no way to repeat the line that caused the error except to add additional logic to duplicate the line if the error can be corrected. I sincerely hope that future versions of Visual Basic Script address this shortcoming.

Exit Function
The Exit function can be placed anywhere within your procedure to immediately exit the function and return control to the line that invoked it. The Exit Function statement is not required since once reaching the End Function line, the function is exited anyway. The Exit Functions most likely use would be to exit the function after an error had occurred or if some other special condition occured

where you would want to immediatle exit the Function.

Procedure Parameters
Procedure parameters are values that are passed to a procedure for processing by that procedure. Procedure parameters are also where a large portion of all program errors occur. The fact that Visual Basic Script is a weakly typed language makes the interface between procedures even more error prone since you can pass a string where a long is expected. There is no built-in parameter type checking when passing a value to a procedure. So the first order is to make sure that the actual parameters passed to the procedure match the formal parameters of the procedure declaration. Fortunately, Visual Basic Script comes equipped with a set of functions that checks the subtype of the parameter being passed. Table 20.1 enumerates those functions and describes what they do. To use them, you simply place the variant as an argument to the function and check for a true or false. Table 20.1 Functions that Verify a Variable's Subtype Name IsArray() IsDate() IsEmpty() IsNull() IsObject() Description Returns a Boolean indicating if variant is an array Returns a Boolean indicating if variant contains a date Returns a Boolean indicating if variant is uninitialized Returns a Boolean indicating if variant contains a Null Returns a Boolean indicating if variant contains an object

IsNumeric() Returns a Boolean indicating if variant contains a number

In Listing 20.5, you may notice that I wrapped the functionality of the procedure in an If...Then...Else statement. This ensures that the procedures code logic is run only if the parameter passed to the function is of a valid type. If the procedure is also sensitive to range values then you should also check for a valid range of values before proceeding with procedure logic. Theres no sense in allowing a divide by zero or overflow error to stop your code. The type checking doesnt include checking for a string or for a long, double, or other specific number type. The number types automatically adjust to the values they contain. If you want to coerce a value to a particular type, you can do so using the conversion functions. If you really need to confirm that a variant contains a string, you have to do it through a process of eliminating the other possible types so that the only possible type left is a string. Listing 20.5 Checking the Sub Type of a Variant General Syntax: boolean = IsNumeric(variable) boolean: value retrned indicating if it is the required type variable: name of the variable to check Public Function Foo(MyParameter)

If IsNumeric(MyParameter) Then do whatever the procedure is supposed to do and return the expected value Foo = ResultValue Else oops, wrong type passed tell the calling procedure we have an error here so return an error value Foo = CVErr(INVALID_SUB_TYPE) End If End Function When declaring the procedures parameters, use a consistent method of ordering them. Many of the experts, like Steve McConnel of Code Complete fame (Microsoft Press 1993), suggest the use of the input-modify-output order of arranging your parameter declarations. You can use an alphabetical, datatype, or other arrangement, but be consistent in your choice. The input-modify-output order implies that you place input only parameters first, modifiable parameters second, and output only parameters last. Also, if you are using the same parameters in several different procedures, make sure they are consistently placed in the same order so you dont get confused between them. Dont include arguments that are not going to be used by your procedure. If you decide that the parameter is not needed, then remove it from the declaration.

Strategies for Good Code Design


Visual Basic Script is a structured programming language with many weak parts in its design. Among the most obvious drawbacks is weakly typed variables. Another is the very limited options for error handling. If this was a full-blown programming environment it would be a nightmare to work with; but its target audience is the limited environment of a scripting language for Web browsers, servers, and other applications that require limited scripting capability. With that in mind, Ill discuss some programming strategies using Visual Basic Script.

Encapsulation of Your Code


Encapsulation of your code and data as much as possible has the effect of containing logic and programming errors into discrete areas that can be more easily diagnosed and corrected. This is one of the main driving forces behind the OOP programming paradigm that has been permeating almost every aspect of the industry. Unfortunately, Visual Basic Script does not include the class/object creation capabilities of Visual Basic itself. Even more dangerous is that you can write code that runs outside of a procedure definition. This has the effect of letting you write a set of code that works every time you load the page, but can open the door to writing large inline code blocks without any structure at all. HTML is like this as well, but, with HTML, you have a very limited ability to do anything on the client side. With the introduction of scripting languages like Java, JavaScript, and Visual Basic Script, the limitations are rapidly disappearing.

For those coming from an HTML background and limited programming experience, you should begin adopting habits right now that make your scripts more readable and maintainable. Some of the key concepts of encapsulated code follow. Limiting Information Hiding the internal workings of a procedure as much as possible from the rest of your application helps prevent you from abusing the purpose of that procedure and introducing errors. Once you design, debug, and test a procedure to produce a given result, leave it alone. If you need added functionality then write another procedure to produce that functionality. You can even wrap the original procedure within another procedure and modify its results to get the added functionality, but dont modify the original procedure itself if it is already being called by other procedures. Loose Coupled Code Another aid to encapsulation is loose coupling between procedures. This means that procedures should have a minimal dependency upon each other. A procedure should be entirely self dependent for its results and not rely on another procedures validity. Dont assume that a procedure you are calling will always work. Later modifications to another procedure can introduce errors in your procedure. If your procedure requires arguments then check those arguments for proper value range and type, and introduce a graceful exit for that procedure if the arguments do not meet specification. Conversely, if you are calling a procedure whose results your procedure depends upon, then include code that protects your procedure should the procedures you are calling fail. If you are calling functions that are returning values then also check those values for proper range and type. If your procedure is supposed to supply a value then make sure that it returns a value of some sort regardless of whether it succeeds or fails in its purpose. In Visual Basic Script, you can convert a functions return value to an error value to indicate that an error has occurred in your procedure. Naming Conventions Another, very important aspect of design for your Visual Basic Scripts is using naming conventions that clearly explain what your code does. As an example, look at Listing 20.7. Obviously, this procedure is the click event of a control. The two lines of code contained in the procedure dont do much in the way of explaining themselves. Can you recognize their purpose?

Listing 20.7 CH9_1.HTMPoor Procedure Naming Practices Sub sprlbl1_Click ChgLblDrctn ChgLblClr

End Sub Okay, if you cant be sure what these lines of code do then maybe we should look at the underlying code within these two procedure calls. Listing 20.8 contains the code for both procedures. The first procedure, ChgLblDrctn doesnt tell you much except that it reverses a value from a positive to a negative and back again. There is No indicationof what the value is used for though Looking at the next procedure, upon seeing the lbl, you can deduce that it changes the forecolor of a label. Well, thats what the procedure does all right, but can you tell me what colors it changes the forecolor to? This procedure is using what many programmers refer to as magic numbers! Magic numbers are literal values that magically accomplish a purpose without you knowing what or how. If you understand the RGB palette system that Windows uses then you recognize that these magic numbers are the three primary colors of red, green, blue, and also black. Even if you figure out the procedures entire purpose and the meanings of the parameters it uses, you must interupt your reading of the code to think about it. Now imagine having to debug several hundred lines of code written in this style.

Listing 20.8 CH9_1.HTMMore Poor Naming Practices Sub ChgLblDrctn lngRtn = lngRtn * -1 End Sub Sub ChgLblClr If SPRLBL1.Forecolor = &HFF Then SPRLBL1.Forecolor = &HFF0000 ElseIf SPRLBL1.Forecolor=&HFF0000 Then SPRLBL1.Forecolor = &HFF00 ElseIf SPRLBL1.Forecolor=&HFF00 Then SPRLBL1.Forecolor=&H0 Else SPRLBL1.Forecolor=&HFF END IF End Sub Now lets look at the same procedures done with informative names and naming conventions. Listing 20.9 shows the labels click event calling procedures with informative names. The first procedure changes the direction of the label. The second procedure leaves no doubt that its purpose is to change the labels color.

Listing 20.9 CH9_1.HTMThe Right Way to Name Procedures Sub sprlbl1_Click ChangeLabelDirection ChangeLabelColor End Sub Okay, we really dont need to look any further because we already know what the procedures do to a fair degree. But I want to know what colors it changes to and what direction is being changed (see Listing 20.10).

Listing 20.10 CH9_1.HTMMore Self Documenting Code! Sub ChangLabelDirection lngRotation = lngRotation * -1 End Sub Sub ChangeLabelColor If Sprlbl.Forecolor = CLR_RED THEN Sprlbl.Forecolor = CLR_BLUE ElseIf Sprlbl.Forecolor=CLR_BLUE THEN Sprlbl.Forecolor = CLR_GREEN ElseIf Sprlbl.Forecolor=CLR_GREEN THEN Sprlbl.Forecolor=CLR_BLACK Else Sprlbl.Forecolor=CLR_RED END IF End Sub Looking at the ChangeLabelDirection procedure I see a variable named lblRotation, which leaves me with no doubt that the purpose of the procedure is to change the rotation direction of the label. The second procedure lets me know what colors are being used because the magic numbers are replaced with descriptive constants. Notice that the constants are all uppercase with an underscore between the prefix and the color name. Altogether, this is what you call self documenting code. This is part of a naming convention that I use and is similar to the one that Microsoft suggests. You can use any convention you want including one you devise on your own. Just use it consistently and document the rules of your naming conventions so that others using your code can understand what you are doing. Listing 20.11 shows a code header in a script module that explains to the reader what conventions are being used in the accompanying code.

Listing 20.11 CH9_1.HTMDocumenting Your Naming Conventions '================================================ 'This Script Module Contains all Constant and 'Global Variables as well as Initialization code 'constants should be all upper case with 'underscores between words: MY_CONSTANT 'other variables should use identity prefixes 'Prefix Meaning 'bln Boolean 'byt Byte 'dtm Date/Time 'dbl Double 'Err Error 'int Integer 'lng Long 'obj Object 'sng Single 'str String '================================================ 'make all declarations explicitly declared '===============Constant Declarations============ 'instead of using literals for values that are 'repeatedly used, setup constants with names 'that fully explain what they do DIM CLR_WHITE CLR_WHITE = &HFFFFFF DIM CLR_BLACK CLR_BLACK = &H000000 DIM CLR_RED CLR_RED = &H0000FF DIM CLR_GREEN CLR_GREEN = &H00FF00 DIM CLR_BLUE CLR_BLUE = &HFF0000

What Is a Good Reason for a Procedure?


When deciding where to place a certain functionality into a procedure you first must understand what a procedure is or should be. A procedure should be a block of code that is called upon for a single purpose. That procedure may call several other procedures to accomplish its purpose, but its very existence should only be for that single purpose. When you have recognized the need for a discrete

procedure, then you have the justification for a procedure. A discrete procedure can be identified as any purpose that includes one of more of the following items:
q q q q q q

Functionality involves more than one line of code. Functionality can be used by more than one other procedure. Functionality can introduce errors into a program. Functionality can be self-contained. Functionality involves complex calculations. Functionality can return a value.

Some might argue the preceding list, but these have usually been the best arguments for creating a discreet function or subroutine. Your procedures should act like a black box in that the calling procedure should only know what it does, not how it does it. If you go back to Listing 20.9 and look at the sprlbl1_Click event, you not only fully understand what each of the contained procedures do, you are not confronted with any complex logic either. The complexity is kept within the procedures that actually do the discrete tasks required. From that, you build the next layer that controls the order and circumstances that these discrete tasks are called. Even further up the ladder of the hierarchy might be the user interface that responds to user events. In the case of this example of Visual Basic Script being used with an HTML document, the HTML code actually provides the upper hierarchy portion of this design. You can design your Visual Basic Scripts to interact as a single layer under the HTML code but you soon find the more complex pages become near impossible to maintain. Design your VBScript scripts to take full advantage of the encapsulation techniques available and break discreet functionality into maintainable procedures. FIG. 20.1 The black box procedure.

Should It Be a Sub or a Function?


I started to say that you should use functions when a return value is expected and subroutines when no return value is expected. While true enough, it begs a much more precise response. Whether your procedure should be a subroutine or function can be directly tied to whether the calling procedure is dependent on the success or failure of the procedure its calling. That is to say, if the procedures failure does not adversely affect the calling procedures purpose, then a subroutine is adequate. But if the calling procedure requires the procedure to succeed in order for itself to succeed then it must be a function. Lets add another functionality to our rotating label project. I want to control the speed of the rotation by entering a number that represents the degrees of rotation with every clock tick. I need a textbox in which to enter the desired speed and a button control to register the speed change. I call the textbox txtDegrees and the button btnSpeed. The idea is that I enter some value into the textbox, click the button, and, in the click event, I change the value of lngRotate to reflect that new value (see Listing 20.12).

Listing 20.12 CH9_1.HTMShould This Be a Discrete Procedure? Sub btnSpeed_OnClick lngRotation = txtDegrees.Value End Sub Its simple, only one line long, and understandable. So what is wrong with this code? The functionality can introduce errors into the program! What happens if the user enters a number out of the accepted range? What happens if the user enters a non-numeric value? You generate an error and bring the script to a halt. Now remember, you dont want to clutter up the second layer of code with the complexity of a discrete process so you create a procedure to handle this. I dont want to pass too much information to the procedure so I limit it to just the value of the txtDegrees and expect it to return a valid value for lblRotation (see Listing 20.13).

Listing 20.13 CH9_1.HTMMoving Things to a Discrete Procedure Function CheckSpeed(lngSpeed) 'first make sure that it is a number If IsNumeric(lngSpeed) Then 'now make sure it is within range If lngSpeed > 45 Or lngSpeed <1 then 'if not within range return 'a default value and warn the user alert "Speed Must be between 1 & 45" CheckSpeed = 5 Else 'its a valid entry so return it CheckSpeed = lngSpeed End If Else 'its not a number so complain 'about it and return a default value alert "Must be a numeric value" CheckSpeed = 5 End If End Function

This function procedure first checks to see if the argument is of the right data type and, if it is, checks to see if the value of the argument is within a specified range. In essence, no matter what the user enters into the textbox this function returns a valid value that allows the purpose of the application to continue. The possible errors are contained within this procedure and not allowed to percolate upwards in the hierarchy. You now have a function procedure that performs the required process. Do you know what the process it performs is? Its not the changing of the rotation speed. Thats the purpose of the click event. The purpose is to validate the users data entry. Listing 20.14 shows the click event using our function procedure.

Listing 20.14 CH9_1Click Event with Validated User Input Sub BtnSpeed_OnClick lngRotation = CheckSpeed(txtDegrees.Value) End sub Once again you can see the effects of self-documenting code. At a glance, you can see that the click event sets the rotation speed of the label after checking the validity of the value in txtDegrees. The idea is to design your procedures so they are as bulletproof as possible and completely safe from external circumstances crashing them. The modified Label rotation example is illustrated in Figure 20.2. FIG. 20.2 The rotating label example with the speed modification.

Applying Structured Techniques


Tired of rotating labels yet? Okay, lets move on to some serious application development. In Chapters 12 and 13 we develop a database application that allows the user to browse or search a catalog of products and make an order. We can start to lay out the overall design for the product catalog here. I base this example on a database model that has equivalents in both Access and SQL Server 6.5, but I refer to the publishers demo database example in SQL Server 6. If you only have VB4 or Access then you have to use the BIBLIO.MDB database and modify the table names accordingly as this project takes shape.

The HTML Document


An HTML document already has clearly defined divisions within it. There is the head, body, or frames. The head section of an HTML document is used to describe that document. The body

contains the active content of the document such as forms, objects, and VBScript. How to use these areas is explained in Chapter 3. The Visual Basic Script area of the document is usually the last group of sections in the document. There are no hard coded rules that require this, but good organization of your HTML document probably causes you to gravitate towards this convention anyway. Youll also see that I further divide the scripting area into three functional sections that help to make your code more understandable by subsequent editors (see fig. 20.3). Remember, you just might be one of those subsequent editors that is trying to remember why you did what you did. FIG. 20.3 Organizing your application's Visual Basic Scripts. In any case, coming from a Visual Basic background, Ive become accustomed to the way things are organized in that environment, and it is heavily influencing the suggestions I make here. As your scripts become more involved the initial organization presented here will go a long way towards helping you keep a handle on things.

The General Declarations Area


In Visual Basic, the General Declarations area is where all module-wide variables, DLL declarations, and object references are declared. In Visual Basic Script, I am suggesting that this practice also be followed. You may also want to provide a header that describes your naming conventions, as shown in listing 19.13. While Visual Basic Script only has the variant type available, it is still a good idea to identify the subtype of the value it contains by using meaningful prefixes. Visual Basic Script does not directly support constants, but you can create and clearly identify constants using one of two conventions. The first is to use all uppercase characters and separate words with an underscore, which is the convention I use in this book. Another valid convention is to use the prefix cst to identify constants. What is important is that you do adopt a consistent method of documentation. Besides using this area as the place for declarations, you can also define initialization code. Unlike Visual Basic, where you must place all code within a defined procedure, Visual Basic Script allows you to place code outside of procedures. The code you place outside of a procedure runs every time the document is loaded into the browser (see Listing 20.15). If you need to utilize this feature, it is best to place that code in the General Declarations area script so its presence is immediately recognized later by you or someone else who might need to understand or edit the document. Another advantage to consider is you can develop a declarations area script that is generic and can be used in all your projects with slight modification.

Listing 20.15 SCRIPTTEMPLATE.TXTSuggested Outline of a Declarations Area Script <SCRIPT LANGUAGE="VBS">

<!-'===================================== ' General Declarations Area '===================================== ' '=========Prefix Conventions========== 'Data Types 'ary = Array bln = Boolean 'byt = Byte cur = Currency 'dbl = Double dte = Date 'err = Error int = Integer 'lng = Long obj = Object 'sng = single str = String ' 'Controls 'btn = Command Button cmb = ComboBox 'cht = Chart Control lbl = Label Control 'lst = List control txt = TextBox ' '=============Constants=============== 'declare constants here with explanation '=========Public Varaibles============ 'declare variables here with explanation '=====Inititialization Procedures======= ' 'place code here that you want to run 'every time the page is loaded --> </SCRIPT>

The Event Procedures Area


Event procedures are usually called through the actions of the user such as a clicking a button, selecting an item from a combo box, or entering text into a text field. There are also other events like the Timer_Time event that is program controlled or the VRML collision event; these are independent of user interaction. Regardless of what the event is, they should be placed in a script whose purpose is to only contain events. Within the event procedures you can call the user defined procedures that produce the desired reaction to those events. Very little actual computational code should be placed at this level. Think of the Event level scripts as the medium for controlling logic flow, not as the place for the actual computational logic. An observer should be able to look at your event procedures and understand exactly what they do without having to spend time figuring out the arcane logic of your computational code. Listing 20.10 shows an event procedure with one line of code that simply sets the value of rotation according to the checked value of a textbox. There is underlying logic that checks the value of that textbox for type and range, and returns a safe value for the lngRotation value; but all of that is hidden in a detail

procedure that you dont need to see to understand the event procedures purpose. Its purpose is to change the value of the rotation rate according to what is in the textbox.

The Detail Procedures Area


This section should contain all the detail procedures that actually perform calculations, control graphic renderings, submit forms, and all other detail logic of your documents program. You should not include any event procedures here at all. Your procedures at this level should provide for error trapping and handling to make sure that generated errors do not percolate upward enough to lock up the browser or even stop the documents functionality. This is a very important concept to consider. Many of the HTML documents you author will be used by people who are not very computer literate. The computer and the Internet are rapidly becoming a household commodity with the inherent lack of computer experience many of these new users have. A lockup or even a non-responsive Web page frustrates and even upsets many who are not at all cognizant of what is going on. Thats not a fault of the user, its a fault of the technology that didnt insulate them from these potential problems. Write your detail procedures so they are capable of handling any logic or user error. Design into your logic a way to degrade gracefully without unduly alarming the user of your page. And, finally, if there is no other alternative, then inform him that an error has occurred through a message box and suggest to him how to recover. Procedures that return a value should always check to ensure that the value they return is within reasonable limits given their purpose.

From Here...
In this chapter I went over the syntax of creating function and subroutine procedures. If you are an experienced programmer, you will immediately miss the ability to alter the values of arguments passed to a procedure. It seems that the only work around to this is to allow your variables a wider scope that crosses procedure boundaries. Be sure to incorporate adequate type and bounds checking within you procedures to account for this. The proposal to arrange your code into three levels of Script, Initialization, Event, and Utility is not a hard wired rule that you must follow. It is more a suggestion that you adopt or develop an organizational and naming convention that helps to make your scripts easier to understand and maintain.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |

| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 20 - VBScript Forms, Controls, and Managing Transactions


by Ron Schwarz

In this chapter
q q q q q q

q q

Designing Forms Using the ActiveX Control Pad Create input and presentation forms that behave like real programs. Sending Data To a Server Learn how to send information to the Web server. Receiving Data From a Server Sending data is fairly easy, but receiving dataespecially when you want to avoid replacing the current page with a query results pageis decidedly non-trivial. Updating the Existing Page Standard HTML pages cannot be updated once they're displayed. To show new data when received from a server, it's necessary to replace the whole page. VBScript and HTML Layout Page technology make it possible to receive and display new data without replacing the current page.

The new HTML Layout Page features, combined with VBScript techniques, make it possible to do the hitherto unthinkablecreate a web page that behaves like a real program, rather than a "soupedup" document. Although there's a fair amount of work involved, and several layers of interlocked logic are required, it's definitely something you should consider using if you want your work to appear as professional as possible. The example in this chapter demonstrates everything you'll need to know to accomplish this on the client end. You'll also need to provide something on the server end to supply the data you're requesting. That's covered in Chapter 21, "Accessing Data." The discussion of the project in this chapter assumes that you've loaded the project from the CD into your copy of the ActiveX Control Pad. To do this, right-click the icon for the Validation.htm file. When the pop-up menu appears, select the entry to load it into the ActiveX Control Pad.

Creating a Web Application


The example presented in this chapter uses the sample Publishers database supplied with Microsoft SQL Server 6.5. The principles involved in sending, receiving, and presenting data can be used with whatever type of system you're using, as long as it can be configured to return its data in the form of an HTML page based on a template you design. The steps involved in creating an application such as this example are these: 1.Define the nature of the transactions (such as what data sent, and what data received). 2.Create the database on the server. 3.Design the form with the ActiveX Control Pad. 4.Write supporting code for data transfer and control handling.

Hiding Data in a Frame


Due to the reluctance of HTML to support true two-way interactivity, retrieving data into the current screen requires some fancy footwork. The approach taken in this chapter consists of a bit of apparent deception; we "trick" Internet Explorer into thinking it's receiving a new page by using a near-hidden frame as a type of data buffer. The reason it's "near" hidden is because it's not possible to completely hide a frame; however, by sizing it to one pixel by one pixel, it will be a light gray spot on a gray background. Even if you know what you're looking for, and where on the screen to look, you'll have a hard time finding it. By hiding incoming data in this frame, you make it available to your script, and you can extract, manipulate, and display it any way you choose. You are no longer at the mercy of HTML.

Handling Queries
After you've created your database, you'll need to have code on the server to respond to queries and create HTML content. Two queries are used in this example. One creates a list of Publishers, and one returns a list of books. Each query consists of two files: an .IDC file, which contains the actual SQL statement, and an .HTX file, which contains an HTML template. This example uses the Internet Data Control (IDC), which is described in Chapter 21, "Accessing Data." Listing 20.1 shows the SQL statement used to create the query that returns a list of all publishers in the database. It's not necessary for you to understand SQL in order to create VBScript to create applications like the example in this chapter, if you have someone available to handle that end of the job. This is feasible because the client and server ends of the project are completely separate. The one line you need to pay attention to defines the .HTX template file that the query uses for output. In this

case, it's pub.htx, as shown in the third line.

Listing 20.1pub.idc Publishers SQL Statement File Datasource: Publishers Username: sa Template: pub.htx SQLStatement: +SELECT Publishers.Pub_ID, +Publishers.Pub_Name, +HighPrice = Max(price), +LowPrice = Min(price) +FROM Publishers, +Titles +WHERE Publishers.pub_id = +Titles.Pub_ID +GROUP BY Publishers.pub_id, Pub_Name Listing 20.2 appears at first glance to be fairly standard HTML, with the addition of an ActiveX ListBox control (lstPublishers), contained in an <OBJECT> tag, and a short script at the end of the file. One thing you should notice is the inclusion of a series of placeholders in the script, such as "<% Pub_Name%>". These contain instructions for the Internet Data Control, telling it what data to insert. The inserted data will replace the placeholders in the HTML file that is sent to your buffer frame. Everything between the <%begindetail%> and <%enddetail%> placeholder will be duplicated one time for each record in the result set created by the query.

Listing 20.2pub.htx Publishers HTML Template File <HTML> <HEAD><TITLE>Publishers List</TITLE></HEAD> <BODY> <BODY BGCOLOR="FFFFFF"> <OBJECT ID="lstPublishers" WIDTH=90 HEIGHT=90 CLASSID="CLSID:8BD21D20-EC42-11CE-9E0D-00AA006002F3"> <PARAM NAME="ScrollBars" VALUE="3"> <PARAM NAME="DisplayStyle" VALUE="2"> <PARAM NAME="Size" VALUE="5151;811"> <PARAM NAME="MatchEntry" VALUE="0">

<PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <Script Language="VBScript"> <%begindetail%> lstPublishers.AddItem "<%Pub_Name%>" & ";" & _ "<%Pub_ID%>" & ";" & _ "<%HighPrice%>" & ";" & _ "<%LowPrice%>" <%enddetail%> Top.TriggerPub </script> </BODY> </HTML> Right after the result definition, you'll see a VBScript statement of Top.TriggerPub. This is a call to a procedure in the application that tells it that the data is loaded into the buffer, and it's OK to proceed to display it in the form. This file is typical of those you'll encounter when using Microsoft SQL Server 6.5 and the IDC. If you're using different server-end software, your queries will have to be handled accordingly. The server-end details are irrelevant to your work with VBScript and the ActiveX Control Pad, as long as the server is able to accept a query and return an HTML page. Listing 20.3 contains the Titles query, which returns a list of books via the Titles.htx template. The same rules described for listing 20.1 also apply here.

Listing 20.3titles.idc Titles SQL Statement File Datasource: Publishers Username: sa Template: Titles.htx SQLStatement: +SELECT Distinct Titles.*, +Publishers.*, +titleAuthor.*, +Authors.* +FROM Titles Join Publishers +on titles.Pub_ID = publishers.Pub_ID +Left Join titleauthor on +Titles.title_id = titleauthor.title_id

+Join Authors on titleauthor.au_id = authors.au_id +WHERE Titles.Price >= Convert(money, '%LowPrice%') +AND Titles.Price <= Convert(Money, '%HighPrice%') +AND Publishers.Pub_id ='%PubID%' Listing 20.4 is similar in concept to the file in listing 20.2, and the same rules apply. As in that file, the script ends with a VBScript call to a procedure in your project; in this case, it's a procedure named Top.TriggerTitle.

Listing 20.4titles.htx Titles HTML Template File <HTML> <HEAD><TITLE>Authors and YTD Sales</TITLE></HEAD> <BODY> <BODY BGCOLOR="FFFFFF"> <OBJECT ID="lstBooks" WIDTH=100 HEIGHT=100 CLASSID="CLSID:8BD21D20-EC42-11CE-9E0D-00AA006002F3"> <PARAM NAME="ScrollBars" VALUE="3"> <PARAM NAME="DisplayStyle" VALUE="2"> <PARAM NAME="Size" VALUE="5151;811"> <PARAM NAME="MatchEntry" VALUE="0"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <Script Language="VBScript"> Dim strBuffer On Error Resume Next <%begindetail%> lstBooks.AddItem "<%title%>" & ", " & "<%au_fname%>" & " " & _ "<%au_lname%>" & ", " & "<%Price%>" <%enddetail%> <%Query_String%> <%Remote_User%> <%request_Method%> Top.TriggerTitle </Script> </BODY> </HTML> In Listings 20.2 and 20.4, the script created by the query exists solely for the purpose of loading a ListBox with the results of the query. This forms the basis of the buffer. Once your application is

notified that the buffer is loaded, it can proceed to extract the data from the ListBox and perform whatever processing is required.

Using HTML Layout Page Forms


The client end of the project consists of two filesan HTML file and an .ALX file. The HTML file contains a small amount of standard HTML code and a reference to the .ALX file. The actual Layout Page is contained in the .ALX file. Figure 20.1 shows the HTML file loaded into the ActiveX Control Pad. FIG. 20.1 Validation.htm is loaded into ActiveX Control Pad.

As this book goes to press, HTML Layout Pages must reside in separate .ALX files. Microsoft plans to make it possible for them to reside in the same file as the HTML portion of a project as soon as the World Wide Web Consortium standards committees settle on the syntax.

Listing 20.5 contains three significant sections (apart from the usual HTML tags (such as, <HTML>, <HEAD>, <BODY>, and so on). The <iFRAME> tag defines the nearly-hidden buffer frame, named frmBuffer. As mentioned, it has a width and height of 1, which makes it for all intents and purposes invisible. Because it's in the main HTML file (it's not possible to place it in an HTML Layout Page), it's declared here, and its one-pixel display will appear outside the Layout Page.

Listing 20.5validation.htm Main HTML form for Validation Example <HTML> <HEAD> <TITLE>Validation Example</TITLE> </HEAD> <BODY> <iFRAME src="" WIDTH=1 HEIGHT=1 NAME="fraBuffer" OnLoad = "Foo"> <FRAME src="" WIDTH=1 HEIGHT=1 NAME="fraBuffer" OnLoad = "Foo"> </iFRAME>

<OBJECT ID="Validation" CLASSID="CLSID:812AE312-8B8E-11CF-93C8-00AA00C08FDF"> <PARAM NAME="ALXPATH" REF VALUE="validation.alx"> </OBJECT> <SCRIPT LANGUAGE="VBScript" OnLoad="InitALX"> Sub TriggerPub Validation.txtTrigger.Text = "pub" End Sub Sub TriggerTitle Validation.txtTrigger.Text = "title" End Sub </SCRIPT> </BODY> </HTML> The second section to observe is the declaration beginning with <OBJECT ID="Validation". This is the declaration for the HTML Layout Page, which is named Validation, and is contained in the validation.alx file. The script is notable because it contains an OnLoad="InitALX" parameter in its declaration. This assures that the script is linked to the HTML Layout Pad. Without that parameter, procedures in the script would not be able to communicate with objects in the Layout Page. The actual script contains two simple procedures, used to create a link between the buffer frame, and the Layout Page. The first, TriggerPub, is called by the Top.TriggerPub statement in the page returned by the server when requesting a list of publishers. Sub TriggerPub Validation.txtTrigger.Text = "pub" End Sub The one line of code in the routine sets the value of a hidden TextBox (txtTrigger in the Validation Layout Page) to "pub". Because limitations in the current version of VBScript, this is the easiest way to invoke a routine in a Layout Page. When the contents of the control change, an event is fired, which the script intercepts and uses as notification that the data is loaded in the buffer and ready to go. Sub TriggerTitle Validation.txtTrigger.Text = "title" End Sub The TriggerTitle procedure is identical to the TriggerPub procedure, except that it sets the value of

the TextBox to "title", indicating that the list of book titles is received and ready for processing. This small HTML page is all that's required to create a foundation for the HTML Layout Page and provide a means to move data in dynamically.

Using ActiveX Controls on Layout Page Forms


The ActiveX Control Pad provides an ideal environment for creating data input and display forms. This project uses a number of visible, and hidden controls. The complete form, with the hidden controls exposed in the Layout editor is shown in Figure 20.2. See Chapters 3, "Introducing the ActiveX Control Pad," and 4, "Creating a Standard HTML Page," for more on this subject. FIG. 20.2 Here's the complete form with all controls visible. The controls at the bottom of Figure 20.2 are three ListBoxes and one TextBox.

The pre-release version of VBScript available as this book goes to press does not provide reliable use of arrays; therefore, hidden ListBoxes are used in their place. Sometimes you will want to use ListBoxes instead of arrays even after the final release versions of Internet Explorer and VBS are available. For instance, you can sort the contents of a ListBox by simply setting the value of a property, which is quite a bit easier than writing your own sort routine in VBS. You can also insert or remove specific elements from a ListBox with one method call, also much easier than doing the same work in VBS code.

Because there's quite a bit going on here, it's necessary to hopscotch around in the script in order to adequately describe it. Bear with the discussion, because once you understand the principles involved, you'll be able to create knock-em-dead presentations; the payoff will be well worth the effort.

Debugging Tip When you're using hidden controls, you may want to make them visible during your initial testing, so that you can see what's going on in them. This can save you hours of

frustration, as well as eliminate the need to salt your code with numerous MsgBox statements to report on the status of variables. After testing, be sure to use the Properties window (shown in fig. 20.3) to set the Visible property of your hidden controls to Falseand, for good measure, move the border of your form to cover them (also shown in fig. 20.3).

FIG. 20.3 Here's the form with the controls hidden. When you want to edit your Layout code in the ActiveX Control Pad, you have two choices: you can load it into Notepad (via the View Source Code selection available when right-clicking over the form in the Layout Page editor), or you can use the Script Wizard (also available via the right-click pop-up menu). You may choose to do a little of each. It's very convenient to have the Script Wizard create event and procedure headers and insert method calls (see fig. 20.4). It's also very handy to be able to navigate the object trees, if for no other reason than to have ready access to a visible representation of the structure. FIG. 20.4 This is the ActiveX Control Pad Script Wizard.

Once you've entered the bulk of your code, you may find it easier to hop back and forth by loading the entire file into Notepad. Be careful to avoid having dual versions of the same file. For instance, let's say you have the project loaded into the Control Pad and decide to load the file into Notepad. After doing some work in Notepad, you decide to browse the object trees in the Control Pad to check out the spelling of a certain object you want to add. While there, you get a phone call, and fifteen minutes later, you say, "Hmm, now where was I?" You look at your monitor, find your place in the object tree, and remember that you were looking for a property event. You find the event, and without giving it a second thought, click it, enter your code into the Control Pad, and then save the file. At this point, you have one set of changes in the copy in Notepad and a different set of changes in the Control Pad. Reconciling them will be tedious at best, and the potential for disaster is highif you make significant changes in one medium and overwrite them with the other after exiting the first.

The complete code for the Layout Page in this project is contained in Listing 20.9. Although the Control Pad creates multiple scripts, and the actual placement of procedures within them is immaterial to actual order of execution, the procedures in this file have been moved around by hand into more or less their order of execution, to facilitate explanation in this book. VBScript is an eventdriven language, which means that not all things have to happen in any specific order. The code of your real-world applications doesn't have to adhere to any specific order.

Creating a Sample Form


The process of creating a form is fairly straightforward, if not entirely obvious at a glance. The example program starts out in Internet Explorer with an empty form, as shown in Figure 20.5. FIG. 20.5 Here's the beginning of the example project in Internet Explorer. The user sees two ListBoxes, two TextBoxes (both TextBoxes are disabled but visible), and two CommandButtons (one of which is disabled). A Label control contains instructions on how to proceed. The ListBox on the left is titled Publishers, and the button beneath it is captioned Get Publishers. When the user clicks Get Publishers, the application sends a simple command to the server: Top.Frames(fraBuffer).location = "http://iymalluf.rt66.com/eftproot/pub.idc?"

The examples in this chapter use the address of the test server the authors used for development purposes. If you're setting these examples up on your own server, be sure to insert the correct URL in your code.

This statement tells the server to execute the pub.idc query and send the HTML page it creates to the buffer frame (fraBuffer) located on the main HTML page. The Top. prefix specifies that the fraBuffer frame is to be found at the "top" level of the projectthe main HTML page. At this point, the program does nothing. But as soon as the page is loaded into the frame, the Top. TriggerPub statement in the returned page is executed, which invokes the TriggerPub procedure in the main HTML page. TriggerPub contains one line of code: Validation.txtTrigger.Text = "pub"

which sets the contents of the txtTrigger control (on the Layout Page) to "pub". This causes the txtTrigger_Change event (see Listing 20.6) to fire, which brings execution back to the Layout Page. Listing 20.6 txtTrigger Procedure from validation.alx Sub txtTrigger_Change() 'Called by kludge routine in main HTML If Working Then Exit Sub End If Working = True Select Case txtTrigger.Text Case "pub" txtTrigger = "" Working = False LoadPublishers 'to provide ersatz load event for frame Case "title" txtTrigger = "" Working = False LoadTitles 'to provide ersatz load event for frame Case Else MsgBox "Illegal call!: " & txtTrigger.Text txtTrigger = "" Working = False End Select end sub The txtTrigger_Change event contains a Select Case block. This block contains three options. One runs the LoadPublishers procedure, if the hidden TextBox contains "pub", one runs LoadTitles if the TextBox contains "title", and the third one is a catch-all that returns an error message via a MessageBox if anything else is in the control. You'll notice some seemingly extraneous code here. The procedure begins with three lines apparently unrelated to the task at hand: If Working Then Exit Sub End If The code also contains the lines txtTrigger = ""

Working = False in each Case block. This brings up a problem endemic to all event-driven code. When you change the contents of a TextBox, you trigger the TextBox's Change event. That's not necessarily a bad thing; in fact, it's the very "trick" we used to get here in the first place. However, because we want to be able to call this procedure more than once, we have to clear the contents of the TextBox after we use them. But, if we try to arrive here with "title" twice in a row, we'll be replacing "title" with "title", which means there's no change, and hence, no Change event! The solution seems obvious: clear the contents of the TextBox as soon as we've used them. But there's a catch: when you clear the contents of the TextBox, you're changing it. This, in turn, fires off another Change event. Because the event occurs while you're still in the Change event, you invoke what's called cascading events, which is generally considered a very bad thing. In fact, it can quickly crash your program by consuming all stack space, as it repeatedly calls itself. In this example, the event would not cascade too far. In fact, it would only cascade once; the moment it double-fired, the Select Case block would fall through to the third test and report an error, because the empty TextBox does not match either of the two valid options. The solution is an old trick: you use a variable (in this case, one called "Working") to track whether you're in the procedure the first time or are in a cascaded invocation. When the procedure is first run, it checks whether the value of "Working" is True. If it is, the procedure recognizes that it is already executing, and it immediately exits. If it's not, it proceeds. After the TextBox is set to "" to empty it, "Working" is restored to False, to allow the procedure run the next time it's invoked. Because VBScript does not at this time provide a means to create static variables (a static variable, legal in Visual Basic, will retain its value between successive invocations of a procedure) it's necessary to declare "Working" outside of any procedure, to give it global scope. Returning to the development of the example program, the LoadPublishers procedure does as its name impliesit loads the list of publishers from the ListBox contained in the invisible frame. The procedure is shown in Listing 20.7. Listing 20.7 LoadPublishers Procedure from validation.alx Sub LoadPublishers For C = 0 to Top.Frames(fraBuffer).lstPublishers.ListCount -1 WkTxt = Top.Frames(fraBuffer).lstPublishers.List(C) StartPos = Instr(WkTxt, ";")1 lstPub.AddItem Left(WkTxt, StartPos) StartPos = StartPos + 2

EndPos = Instr(StartPos, WkTxt, ";") lstPubID.AddItem Mid(WkTxt, StartPos, EndPosStartPos) StartPos = EndPos + 1 EndPos = Instr(StartPos, WkTxt, ";") lstHighPrice.AddItem Mid(WkTxt, StartPos, EndPosStartPos) StartPos = EndPos + 1 EndPos = Len(WkTxt) lstLowPrice.AddItem Mid(WkTxt, StartPos, EndPosStartPos) Next lstPub.ListIndex = 0 'Select first item. PubID = lstPubID.List(0) 'publisher ID PubMin = CDbl(lstLowPrice.List(0)) 'publisher minumum PubMax = CDbl(lstHighPrice.List(0)) 'publisher maximum lblAbsMin = "(" & PubMin & ")" lblAbsMax = "(" & PubMax & ")" txtMin.Enabled=True 'Allow user to proceed to set Min txtMax.Enabled=True 'Allow user to proceed to set Max cmdTitles.Enabled=True 'Allow user to proceed to get Titles end sub The LoadPublishers procedure takes each entry in the Top.Frames(fraBuffer).lstPublishers ListBox using the following line: For C = 0 to Top.Frames(fraBuffer).lstPublishers.ListCount -1 to count through them. Because the first entry in a ListBox is 0, the count starts at 0 and continues to one less than the value in the ListBox's ListCount property. (ListCount contains the number of items in the list, not the number of the highest item.) The items in the ListBox contain four pieces of data: the publisher's name, the publisher's ID number, the price of the publisher's most expensive book, and the price of its least expensive book. The pieces of data are separated by semicolons. This data is separated into four ListBoxes (the large one on the left of the form and the three hidden ones on the bottom). The publisher's name goes into the visible ListBox, and the other three bits of information are used by the program to validate entry and construct queries. To separate this data, it's first put into a string named "WkTxt" (which stands for work text): WkTxt = Top.Frames(fraBuffer).lstPublishers.List(C) The .List(C) property returns the value of the item at the position represented by C, which is the variable created by the For-Next loop. StartPos = Instr(WkTxt, ";")1

lstPub.AddItem Left(WkTxt, StartPos) "StartPos" a numeric variable, set to contain a value representing a position one character before the position of the first semicolon in the string, using the Instr function, which searches one string for a match with a smaller string. Then "lstPub" (the visible ListBox) is set to the "Left" part of the string (up to but not including the semicolon). StartPos = StartPos + 2 EndPos = Instr(StartPos, WkTxt, ";") lstPubID.AddItem Mid(WkTxt, StartPos, EndPosStartPos) The process is repeated above for the second part of the string. In this case, it's modified, since it's not at the start of the string, therefore, the Left function can't be used. Instead, the Mid function is used to extract characters from within the string. The first line sets StartPos to point one character after the semicolon. The second line creates a new variable, EndPos, which points to the second semicolon. (Instr is invoked here using the optional first parameter, which tells it where in the string to start searching.) Then, the Mid function returns the second item by fetching the characters between the two semicolons. The first parameter in the Mid function ("WkTxt") is the string containing all the bits of data in the item. The second ("StartPos") tells Mid where to start copying characters, and the third parameter contains an expression; the result of "EndPos - StartPos" contains the number of characters to copy. The characters are copied into the invisible lstPubID ListBox, for use later on with the query to the server. StartPos = EndPos + 1 EndPos = Instr(StartPos, WkTxt, ";") lstHighPrice.AddItem Mid(WkTxt, StartPos, EndPosStartPos) The third bit of data is extracted using the identical process as that used for the second, except this time, the retrieved information is loaded into the lstHighPrice invisible ListBox. StartPos = EndPos + 1 EndPos = Len(WkTxt) lstLowPrice.AddItem Mid(WkTxt, StartPos, EndPosStartPos)

Finally, the last part of the item is retrieved. This time, EndPos is simply set to the length of "WkTxt" by use of the Len string handling function. Because there's no closing semicolon, the length of the string marks the last character that's required here. This process is repeated for each item in the ListBox contained in the buffer frame. Then, a few global variables are set: PubID = lstPubID.List(0) 'publisher ID PubMin = CDbl(lstLowPrice.List(0)) 'publisher minumum PubMax = CDbl(lstHighPrice.List(0)) 'publisher maximum PubID, PubMin, and PubMax are described in the comments at the end of each line. PubID is used for the queries of book titles, and the PubMin and PubMax variables are used in data validation. lblAbsMin = "(" & PubMin & ")" lblAbsMax = "(" & PubMax & ")" Two labels on the form are set to display the absolute minimum and maximum prices of all books the current publisher carries. (The "current publisher" is whichever one is highlighted in the Publishers ListBox.) txtMin.Enabled=True 'Allow user to proceed to set Min txtMax.Enabled=True 'Allow user to proceed to set Max cmdTitles.Enabled=True 'Allow user to proceed to get Titles Finally, the three disabled controls are enabled, allowing the user to proceed. Now the program waits for something to happen.

One of the simplest and most effective methods of data validation is preventing entry of invalid data. Intentionally disabling controls when they are not supposed to be used is one effective method of prevention.

At this point, the example will appear as shown in Figure 20.6.

FIG. 20.6 Here's the example project after getting publisher data.

Using Data Validation


You can't always prevent bad data by disabling controls. In this example, the user is expected to select a publisher, then enter a desired range of prices, and submit a query. You can prevent the user from entering prices or sending a query before publisher data is loaded fairly easilyjust disable the relevant controls. But what of the situation after the data is loaded? What happens if the user enters a low price that is lower than the publisher's least expensive title or a high price that is higher than the most expensive? In this case, you could rely on the server to trap the error. But it could take a long time, and it might not even trap it! One of the features of VBScript is the ability to validate data locally, before sending it to the server. In this example, the values entered by the user are validated using a simple set of rules: the user has to enter both numbers; the lowest can't be lower than the least expensive book, the highest can't be higher than the most expensive, and the highest can't be lower than the lowest. If the user clicks Get Titles but hasn't entered any numbers, the application displays an error message as shown in Figure 20.7 FIG. 20.7 In this error example, no minimum value was specified. If the minimum is lower than the least expensive book, the message in Figure 20.8 is shown. FIG. 20.8 In this error example, the minimum value specified was too low. Because the program shows these MessageBoxes instead of simply passing bad data on to the server, the user receives immediate feedback and can correct the situation without waiting for the server to process and pass back its data. This kind of entry-error-prevention also makes it easier for the program to parse incoming data, as it's not necessary to test for these errors when processing query results. When the user clicks Get Titles, the code in the ValidateQuery procedure (shown in Listing 20.8) executes and performs the tests necessary to trap for these errors.

Listing 20.8 ValidateQuery Procedure from validation.alx Sub ValidateQuery() Min = Trim(txtMin.Text) 'Store values to variables Max = Trim(txtMax.Text) If Min = "" Then MsgBox "Must enter a Minimum value!" Exit Sub End If If Max = "" Then MsgBox "Must enter a Maximum value!" Exit Sub End If Min = CDbl(Min) 'Convert variables to numeric Max = CDbl(Max) ErStr = "" 'initialize to empty string If Min > 0 then If Max > Min Then If Min >= PubMin Then If Max <= PubMax Then SubmitTitles Else ErStr = "Max is greater than highest price available!" End If Else ErStr = "Min is less than lowest price available!" End If Else ErStr = "Max must be greater than Min!" End If Else ErStr = "Min must be greater than 0!" End If If ErStr > "" then MsgBox ErStr end sub The code in Listing 20.8 is fairly straightforward and fairly self-documenting. It first checks to make sure the user has entered values; then it tests for all possible error conditions, using a series of nested If-Then blocks. By properly indenting the If-Then tests, you can tell at a glance where each block starts and ends. After all data is accepted as valid, the procedure passes control to the SubmitTitles procedure, which constructs a string containing the query and sends it on its way to the server (see fig. 20.9). FIG. 20.9

Titles are returned when data is validated.

Handling Data Transactions


The SubmitTitles procedure is elegant in its simplicity. All the data having been accepted and validated prior to arrival here, it's relatively trivial to combine it into a query string, and send it to the server. The string consists of the URL of the server, which is comprised of the machine address ("http://iymalluf.rt66.com"), the path containing the query file ("/eftproot/"), the name of the query file ("titles.idc"), a question-mark, which indicates that it's a query to execute rather than a file to fetch, and the query itself: "pubID=" & PubID & "&HighPrice=" & Max & "&LowPrice=" & Min". The query consists of names in the format required by the server ("pubID=", "&HighPrice=", "&LowPrice=") concatenated with the names of the VBScript variables containing the actual data: Sub SubmitTitles() 'query server lstTitles.Clear Top.Frames(fraBuffer).location="http://iymalluf.rt66.com/eftproot/titles.idc? [ic: ccc]pubID=" & PubID & "&HighPrice=" & Max & "&LowPrice=" & Min end sub After this query is sent, the application does nothing until notified that the result file is waiting in the buffer frame, exactly as with the Publishers query. When the result file is received, LoadTitles is executed, and the Titles ListBox is populated with the results. Because the list of book titles doesn't need to be separated into discrete elements, placing it into the ListBox is simple: Sub LoadTitles For C = 0 to Top.Frames(fraBuffer).lstBooks.ListCount -1 lstTitles.AddItem Top.Frames(fraBuffer).lstBooks.List(C) Next end sub The LoadTitles procedure counts through the list of items and adds them, one at a time, to the lstTitles ListBox.

Understanding the Layout Page Source Listing

Listing 20.9 contains the entire source for the HTML Layout Page used in this example. The section after the final script contains declarations for the controls used in the project.

Listing 20.9validation.alx Layout Page Code for Validation Example <SCRIPT LANGUAGE="VBScript"> <!-Dim PubID, PubMin, PubMax, Min, Max, Working Sub txtTrigger_Change() 'Called by kludge routine in main HTML If Working Then Exit Sub End If Working = True Select Case txtTrigger.Text Case "pub" txtTrigger = "" Working = False LoadPublishers 'to provide ersatz load event for frame Case "title" txtTrigger = "" Working = False LoadTitles 'to provide ersatz load event for frame Case Else MsgBox "Illegal call!: " & txtTrigger.Text txtTrigger = "" Working = False End Select end sub Sub ClearPubLists lstPub.Clear lstPubID.Clear lstLowPrice.Clear lstHighPrice.Clear End Sub --> </SCRIPT> <SCRIPT LANGUAGE="VBScript"> <!-Sub cmdPub_Click() ClearPubLists lstTitles.Clear REM query server, load hidden listbox into lstPub

Top.Frames(fraBuffer).location="http://iymalluf.rt66.com/ eftproot/ [ic: ccc]pub.idc?" end sub Sub LoadPublishers For C = 0 to Top.Frames(fraBuffer).lstPublishers.ListCount -1 WkTxt = Top.Frames(fraBuffer).lstPublishers.List(C) StartPos = Instr(WkTxt, ";")1 lstPub.AddItem Left(WkTxt, StartPos) StartPos = StartPos + 2 EndPos = Instr(StartPos, WkTxt, ";") lstPubID.AddItem Mid(WkTxt, StartPos, EndPosStartPos) StartPos = EndPos + 1 EndPos = Instr(StartPos, WkTxt, ";") lstHighPrice.AddItem Mid(WkTxt, StartPos, EndPosStartPos) StartPos = EndPos + 1 EndPos = Len(WkTxt) lstLowPrice.AddItem Mid(WkTxt, StartPos, EndPosStartPos) Next lstPub.ListIndex = 0 'Select first item. PubID = lstPubID.List(0) 'publisher ID PubMin = CDbl(lstLowPrice.List(0)) 'publisher minumum PubMax = CDbl(lstHighPrice.List(0)) 'publisher maximum lblAbsMin = "(" & PubMin & ")" lblAbsMax = "(" & PubMax & ")" txtMin.Enabled=True 'Allow user to proceed to set Min txtMax.Enabled=True 'Allow user to proceed to set Max cmdTitles.Enabled=True 'Allow user to proceed to get Titles end sub --> </SCRIPT> <SCRIPT LANGUAGE="VBScript"> <!-Sub cmdTitles_Click() ValidateQuery end sub Sub ValidateQuery() Min = Trim(txtMin.Text) 'Value) 'Store values to variables Max = Trim(txtMax.Text) 'Value) If Min = "" Then MsgBox "Must enter a Minimum value!" Exit Sub End If If Max = "" Then MsgBox "Must enter a Maximum value!" Exit Sub

End If Min = CDbl(Min) 'Convert variables to numeric Max = CDbl(Max) ErStr = "" 'initialize to empty string If Min > 0 then If Max > Min Then If Min >= PubMin Then If Max <= PubMax Then SubmitTitles Else ErStr = "Max is greater than highest price available!" End If Else ErStr = "Min is less than lowest price available!" End If Else ErStr = "Max must be greater than Min!" End If Else ErStr = "Min must be greater than 0!" End If If ErStr > "" then MsgBox ErStr end sub Sub SubmitTitles() 'query server lstTitles.Clear Top.Frames(fraBuffer).location="http://iymalluf.rt66.com/ eftproot/titles.idc? [ic: ccc]pubID=" & PubID & "&HighPrice=" & Max & "&LowPrice=" & Min end sub Sub LoadTitles For C = 0 to Top.Frames(fraBuffer).lstBooks.ListCount -1 lstTitles.AddItem Top.Frames(fraBuffer).lstBooks.List(C) Next end sub --> </SCRIPT> <SCRIPT LANGUAGE="VBScript"> <!-Sub lstPub_Click() PubID = lstPubID.list(lstPub.ListIndex) 'publisher ID PubMin = CDbl(lstLowPrice.list(lstPub.ListIndex)) 'publisher minumum PubMax = CDbl(lstHighPrice.list(lstPub.ListIndex)) 'publisher maximum lblAbsMin = "(" & PubMin & ")"

lblAbsMax = "(" & PubMax & ")" End Sub --> </SCRIPT> <DIV ID="hlValid" STYLE="LAYOUT:FIXED;WIDTH:519pt; HEIGHT:290pt;"> <OBJECT ID="cmdPub" CLASSID="CLSID:D7053240-CE69-11CD-A777-00DD01143C57" [ic: ccc]STYLE="TOP:206pt;LEFT:33pt;WIDTH:66pt;HEIGHT:25pt; TABINDEX:0;ZINDEX:0;"> <PARAM NAME="Caption" VALUE="Get Publishers"> <PARAM NAME="Size" VALUE="2328;882"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="ParagraphAlign" VALUE="3"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <OBJECT ID="cmdTitles" CLASSID="CLSID:D7053240-CE69-11CD-A777-00DD01143C57" [ic: ccc]STYLE="TOP:206pt;LEFT:385pt;WIDTH:66pt;HEIGHT:25pt; TABINDEX:1;ZINDEX:1;"> <PARAM NAME="VariousPropertyBits" VALUE="25"> <PARAM NAME="Caption" VALUE="Get Titles"> <PARAM NAME="Size" VALUE="2328;882"> <PARAM NAME="FontEffects" VALUE="1073750016"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="ParagraphAlign" VALUE="3"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <OBJECT ID="lblPublishers" CLASSID="CLSID:978C9E23-D4B0-11CE-BF2D-00AA003F40D0" [ic: ccc] STYLE="TOP:8pt;LEFT:34pt;WIDTH:74pt;HEIGHT:17pt; ZINDEX:2;"> <PARAM NAME="Caption" VALUE="Publishers"> <PARAM NAME="PicturePosition" VALUE="393216"> <PARAM NAME="Size" VALUE="2611;600"> <PARAM NAME="BorderStyle" VALUE="1"> <PARAM NAME="FontEffects" VALUE="1073741825"> <PARAM NAME="FontHeight" VALUE="240"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="ParagraphAlign" VALUE="3"> <PARAM NAME="FontWeight" VALUE="700"> </OBJECT> <OBJECT ID="lblTitles"

CLASSID="CLSID:978C9E23-D4B0-11CE-BF2D-00AA003F40D0" [ic: ccc]STYLE="TOP:8pt;LEFT:296pt;WIDTH:50pt;HEIGHT:17pt; ZINDEX:3;"> <PARAM NAME="Caption" VALUE="Titles"> <PARAM NAME="Size" VALUE="1764;600"> <PARAM NAME="BorderStyle" VALUE="1"> <PARAM NAME="FontEffects" VALUE="1073741825"> <PARAM NAME="FontHeight" VALUE="240"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="ParagraphAlign" VALUE="3"> <PARAM NAME="FontWeight" VALUE="700"> </OBJECT> <OBJECT ID="txtMin" CLASSID="CLSID:8BD21D10-EC42-11CE-9E0D-00AA006002F3" [ic: ccc]STYLE="TOP:198pt;LEFT:319pt;WIDTH:41pt;HEIGHT:16pt; TABINDEX:5;ZINDEX:4;"> <PARAM NAME="VariousPropertyBits" VALUE="746604569"> <PARAM NAME="Size" VALUE="1446;564"> <PARAM NAME="FontEffects" VALUE="1073750016"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <OBJECT ID="txtMax" CLASSID="CLSID:8BD21D10-EC42-11CE-9E0D-00AA006002F3" [ic: ccc]STYLE="TOP:223pt;LEFT:319pt;WIDTH:41pt;HEIGHT:16pt; TABINDEX:6;ZINDEX:5;"> <PARAM NAME="VariousPropertyBits" VALUE="746604569"> <PARAM NAME="Size" VALUE="1446;564"> <PARAM NAME="FontEffects" VALUE="1073750016"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <OBJECT ID="lblMin" CLASSID="CLSID:978C9E23-D4B0-11CE-BF2D-00AA003F40D0" [ic: ccc]STYLE="TOP:198pt;LEFT:229pt;WIDTH:41pt;HEIGHT:8pt; ZINDEX:6;"> <PARAM NAME="Caption" VALUE="Min. Price"> <PARAM NAME="Size" VALUE="1446;282"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <OBJECT ID="lblMax"

CLASSID="CLSID:978C9E23-D4B0-11CE-BF2D-00AA003F40D0" [ic: ccc]STYLE="TOP:223pt;LEFT:229pt;WIDTH:41pt;HEIGHT:8pt; ZINDEX:7;"> <PARAM NAME="Caption" VALUE="Max. Price"> <PARAM NAME="Size" VALUE="1446;282"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <OBJECT ID="lblInstructions" CLASSID="CLSID:978C9E23-D4B0-11CE-BF2D-00AA003F40D0" [ic: ccc]STYLE="TOP:256pt;LEFT:121pt;WIDTH:281pt;HEIGHT:25pt; ZINDEX:8;"> <PARAM NAME="Caption" VALUE="Click 'Get Publishers' to [ic: ccc] retrieve list of publishers. Then, enter desired range [ic: ccc] of prices, and click 'Get Titles' to retrieve list of [ic: ccc] titles within range."> <PARAM NAME="Size" VALUE="9913;882"> <PARAM NAME="SpecialEffect" VALUE="2"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <OBJECT ID="txtTrigger" CLASSID="CLSID:8BD21D10-EC42-11CE-9E0D-00AA006002F3" [ic: ccc] STYLE="TOP:322pt;LEFT:289pt;WIDTH:40pt;HEIGHT:17pt; TABINDEX:10; [ic: ccc]DISPLAY:NONEZINDEX:9;"> <PARAM NAME="VariousPropertyBits" VALUE="746604571"> <PARAM NAME="Size" VALUE="1411;600"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <OBJECT ID="lblAbsMin" CLASSID="CLSID:978C9E23-D4B0-11CE-BF2D-00AA003F40D0" [ic: ccc] STYLE="TOP:198pt;LEFT:278pt;WIDTH:26pt;HEIGHT:17pt; ZINDEX:10;"> <PARAM NAME="Size" VALUE="917;600"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <OBJECT ID="lblAbsMax" CLASSID="CLSID:978C9E23-D4B0-11CE-BF2D-00AA003F40D0"

[ic: ccc] STYLE="TOP:223pt;LEFT:278pt;WIDTH:26pt;HEIGHT:17pt; ZINDEX:11;"> <PARAM NAME="Size" VALUE="917;600"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <OBJECT ID="lstTitles" CLASSID="CLSID:8BD21D20-EC42-11CE-9E0D-00AA006002F3" [ic: ccc] STYLE="TOP:33pt;LEFT:150pt;WIDTH:362pt;HEIGHT:155pt; TABINDEX:13; [ic: ccc]ZINDEX:12;"> <PARAM NAME="VariousPropertyBits" VALUE="746586139"> <PARAM NAME="ScrollBars" VALUE="3"> <PARAM NAME="DisplayStyle" VALUE="2"> <PARAM NAME="Size" VALUE="12771;5468"> <PARAM NAME="MatchEntry" VALUE="0"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <OBJECT ID="lstPubID" CLASSID="CLSID:8BD21D20-EC42-11CE-9E0D-00AA006002F3" [ic: ccc] STYLE="TOP:305pt;LEFT:83pt;WIDTH:57pt;HEIGHT:42pt; TABINDEX:16; [ic: ccc]DISPLAY:NONEZINDEX:13;"> <PARAM NAME="ScrollBars" VALUE="3"> <PARAM NAME="DisplayStyle" VALUE="2"> <PARAM NAME="Size" VALUE="2011;1482"> <PARAM NAME="MatchEntry" VALUE="0"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <OBJECT ID="lstPub" CLASSID="CLSID:8BD21D20-EC42-11CE-9E0D-00AA006002F3" [ic: ccc] STYLE="TOP:33pt;LEFT:0pt;WIDTH:146pt;HEIGHT:155pt; TABINDEX:2; [ic: ccc]ZINDEX:14;"> <PARAM NAME="VariousPropertyBits" VALUE="746586139"> <PARAM NAME="ScrollBars" VALUE="3"> <PARAM NAME="DisplayStyle" VALUE="2"> <PARAM NAME="Size" VALUE="5151;5468"> <PARAM NAME="MatchEntry" VALUE="0"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2">

<PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <OBJECT ID="lstHighPrice" CLASSID="CLSID:8BD21D20-EC42-11CE-9E0D-00AA006002F3" [ic: ccc] STYLE="TOP:314pt;LEFT:157pt;WIDTH:57pt;HEIGHT:36pt; TABINDEX:14;DISPLAY: [ic: ccc]NONEZINDEX:15;"> <PARAM NAME="ScrollBars" VALUE="3"> <PARAM NAME="DisplayStyle" VALUE="2"> <PARAM NAME="Size" VALUE="2011;1270"> <PARAM NAME="MatchEntry" VALUE="0"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <OBJECT ID="lstLowPrice" CLASSID="CLSID:8BD21D20-EC42-11CE-9E0D-00AA006002F3" [ic: ccc] STYLE="TOP:314pt;LEFT:223pt;WIDTH:57pt;HEIGHT:35pt; TABINDEX:15; [ic: ccc]DISPLAY:NONEZINDEX:16;"> <PARAM NAME="ScrollBars" VALUE="3"> <PARAM NAME="DisplayStyle" VALUE="2"> <PARAM NAME="Size" VALUE="2011;1235"> <PARAM NAME="MatchEntry" VALUE="0"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> </DIV>

From Here...
The exciting possibilities shown in this chapter require a working knowledge of the HTML Control Pad, HTML Layout Pages, and the VBScript language. To a lesser extent, an understanding of HTML is important.
q

q q

See Chapter 3, "Introducing the ActiveX Control Pad," and Chapter 4, "Creating a Standard HTML Page," for information about using the ActiveX Control Pad. See Chapter 6, "Creating an HTML Layout Page," for more information on using .ALX files with the ActiveX Control Pad. See Chapters 1120 for details on the VBScript language implementation. See Chapter 21, "Accessing Data," for information on creating the server-side logic required to provide data to the client.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 21 - Accessing Data


by Ibrahim Malluf

In this chapter
q q q q q

Using data sources Using server side data The Internet Database Connector (IDC) provides a simple, direct method for accessing data. Using client side data Building query pages

One of the most exiting aspects of recent developments in Web servers is the ability to access Open Database Connectivity (ODBC) data sources directly through interactive queries. Microsofts Internet Information Server (MSIIS), for example, provides the IDC interface that automatically queries the database and returns a result page based on the specifics of an HTX file that describes how the output should be formatted. The process involves three steps: the user submits a request for data to the Web server, the request is processed, and a results page is created and returned to the users browser. Traditionally this has been done through CGI scripts with all processing being done on the server side of things. With VBScript, you can validate the query data and determine what type of query should be submitted and even what the return data should look like. ODBC data sources cover a very wide range of RDBMS from Syquest and Oracle to Microsoft SQLServer and even ISAM databases through the Jet DBEngine. Microsoft Internet Information Server directly accesses these databases using a very simple interface. While you can still develop CGI scripts and use them for data access, the rest of this chapter is about the IDC interface provided by Microsofts Internet Information Server.

Using Data Sources


With the Microsoft Internet Information Server (MSIIS), you can access any ODBC-compliant data source. This includes Access, SQL Server, Oracle, DB2, and many others. This book uses SQLServer and Access for its database examples. When using the ODBC databases in conjunction with

the MSIIS, you have to create the datasource as a DSN entry: 1. Select the ODBC icon from the control panel (NT351). 2. Select the System DSN command button. 3. At this point you should see the dialogs shown in Figure 21.1. Fill in the required information including the database name in the options section. FIG. 21.1 Add a DSN datasource to the system.

Using Server Side Data


On the server side of things, an array of methods is available for processing data. Depending on your platform, you can use CGI, perl, Java, Visual Basic, and many other tools. Our focus here is on the Microsoft Internet Information Server, so our examples discuss the main tool made available for database operations: the Internet Database Connector. The Internet Database Connector (IDC) is an interface between the MSIIS Web server and ODBC data sources. If you are looking for a simple, direct method for accessing data, this is an outstanding choice. It requires three files to produce an HTML results page. The IDC file structure contains the components shown in Table 21.1. Table 21.1 Components of the IDC File Field DataSource Template SQLStatement DefaultParameters Expires MaxFieldSize MaxRecords Password Required Description Yes Yes Yes No No No No No The name of the ODBC Data Source The name of an HTX file that contains the format for the returned data in HTML The SQL statement to be executed The default values for parameters if the client did not specify any Used to specify how long a cached page will remain before being refreshed by the IDC The maximum size of a returned field The maximum number of rows to return The Clients Password (see MIIS Manual) Specifies required parameters; returns an error to the client is parameters are not provided

RequiredParameters No

Username ContentType

No No

A valid user name Any valid Mime Type to be returned to the client

The DataSource, Template, and SQLStatement must be present in every IDC file. The DataSource specifies the ODBC datasource that contains the desired database. When you set this data source up, you must set it up as a SystemDSN. The Template specifies the name of the .HTX file that contains the formatting information for the recordset returned from the query. The file looks just like an HTML file but contains special formatting instructions that modify the output HTML file with special keywords and values. Here are some of those keywords and values with examples of their use. <%begindetail%>...<%enddetail%> These two keywords mark the beginning and end of a merged data row. For each row returned, the details included between them will be repeated (see Listing 21.1). Listing 21.1 Inserting the Data Returned from the IDC into a Web Page <SELECT NAME=AuthorList> <%begindetail%> <OPTION VALUE = <%au_fname%> <%au_lname%> <%enddetai%> </SELECT> This code would add the name of every author returned in the recordset into a dropdown box on the resultant HTML form. <%if...%>...<%Else%>...<%EndIf%> Conditional keywords are provided so that you can include some branching logic in the creation of your HTML page. This If...Else...EndIf structure should be familiar to most BASIC programmers. The conditional statement is contained within the If statement: <%If Conditional%>. There is no Then statement after it (see Listing 21.2). Listing 21.2 Using Conditional Statements in a Template File <%IF CurrentRecord EQ 0%> There are no Authors matching your criteria! <%Else%> <SELECT NAME=AuthorList> <%begindetail%> <OPTION VALUE = <%au_fname%> <%au_lname%> <%enddetai%>

</SELECT> <%EndIf%> Listing 21.2 is a variation on the previous example that creates a dropdown box and adds data to it only if there are rows returned in the rowset. The EQ operator and CurrentRecord value used in this example is explained below. EQ, LT, GT, CONTAINS Operators Along with the keywords, the IDC provides some operators to use with .HTX pages to further increase the flexibility of your page templates. Their meanings are pretty straightforward (see Table 12.2). Table 12.2 HTX Operator Desriptions Name EQ LT GT CONTAINS Description Equals operator. Returns True if both arguments are equal to each other Less Than operator. Returns true if left arguments value is less than the right arguments value Greater Than operator. Returns True if left arguments value is greater than the right arguments value Returns True if the string argument on the left contains the string argument on the right

In the example for the <%If%>...<%Else%>...<%EdnIf%> statement, you saw the EQ operator used. The LT and GT operators work pretty much the same. The CONTAINS operator is a string searching tool that provides a means for you to check for specific values. CurrentRecord, MaxRecords Built-In Variables The CurrentRecord intrinsic variable contains the row number being processed. It is incremented every iteration of the <%begindetail%>...<%enddetail%> pair. The MaxRecords is the value of the MaxRecords field set in the IDC file. If no value was set, it will return 0. Both of these variables only work within the <%If...%><%Else%><%EndIf%> conditional statement. IDC Parameters Your .HTX file can access the parameters originally passed to the .IDX file by the HTML Query page. If one of the criteria parameteers was named %lName% you could access the value of %lName % by using the construct: IDC.lName

HTTP Variables HTTP variables contain information about the client sending the request. The complete header is contained in the ALL_HTTP variable. In addition there are HTTP variables that contain specific information. All of theses variables must be prefaced with the HTTP_ prefix and must be all uppercase characters. Table 21.3 gives a list of some of them. For a more comprehensive list, see the MSIIS Server documentation. Table 21.3 Some HTTP Variables Variable ACCEPT USER_AGENT REFERER AUTH_TYPE Description Describes the type of data the client will accept Client browser information Name of HTML file that called this operation Type of authorization in effect

QUERY_STRING Information following the ? in a URL REMOTE_ADDR IP address of the client REMOTE_HOST The host name of the client REMOTE_USER The username supplied by the client Suppose you had to know what kind of browser client was requesting data, in order to use, or not use, certain features. The IDC provides access to HTTP variables that include that name of the browser. The ALL_HTTP variable contains a header that has the browser type within the string. To check to see whether you were using Explorer 3.0, for example, you might do something like whats shown in Listing 21.3. Listing 21.3 Other Conditionals Based on the HTTP Variables <%IF HTTP_USER_AGENT CONTAINS Explorer/3.0%> ...do something <%Else%> ...do somthein else <%EndIf%> To see exactly how the IDC works, try a simple page using Microsoft Internet Information Server. Looking at Figure 21.2, you can see the steps involved in retrieving data. The first HTML page provides the user with a method of specifying criteria for the search. When the user is done specifying criteria, the criteria are submitted to an .IDC file that gets the resultset and submits it to an . HTX file that formats the data into an HTML page and returns it to the browser. This process can be repeated as many times as you wish, creating a drill-down search with each query returned building a

new set of search options. For now, well try a simple query page that will give you a working example of how things fit together. FIG. 21.2 The Internet Database Connector in action, step by step.

Using Client Side Data


Client side data includes search criteria, data entry, and returned rows from a query. Search criteria uses the input from a user to build a query to submit to the data server. What you most commonly see in Web pages are single-entry searches or searches that allow multiple fields with little control over whether its an or or an and type of relationship. They also dont allow for sophisticated pattern matching queries. Data entry is part of client side data. In the past, Web pages have just passed the entered data back to the server as entered by the user without any qualifications. If there was invalid or incomplete data, this could not be checked until the server passed had the data to the program that was responsible for the response to the query. Errors would be detected there, and the appropriate response would then be sent back to the source of the query. Considering that there are situations involving bandwidth, server load, and other factors that could really slow down the interaction between the client and the server, the ability to screen data before sending it becomes paramount. VBScript gives you that ability.

Building Query Pages


The current limitations of the Web server/browser interface even with VBScript dictate limitations on your interface design. Perhaps the most limiting condition when using the IDC is that the way the data is returned must be already defined and formatted in a preexisting .HTX document. The .HTX format allows you considerable formatting options, but the basic document must preexist. This means is that users are going to be limited to the query structures that you provide. Ad-hoc queries simply wont work using the IDC.

As an introduction into building SQL queries for submission, consider this simple scenario. This page will allow the user to select one of three tables from the PUBS sample database in SQL-Server 6. In order for this example to work, you have to have MIIS and SQL-Server 6 up and running. You must also create an ODBC datasource on your server using the ODBC utility in the control panel of NT 3.51 with service pak4 or from NT4.0. The ODBC source must be set up as a DNS datasource. Use the name Publishers as the name of the datasource and set Pubs as the database name. Using Notepad as your text editor, create the file shown in Listing 21.4 or alternatively, you could retrieve the file from the companion CD. This is an .IDX file that receives the query string from your page and submits it to SQL-Server.

Listing 21.4quepub1.idc An .IDX file that requests a rowset from SQL Server

quepub1.idx Datasource: Web SQL Username: sa Template: quepub1.htx SQLStatement: +SELECT *FROM authors +WHERE au_lname LIKE %lname% +AND au_fname LIKE %fname% This .IDX file takes two arguments, %lname% and %fname%, as parameters for the query. It passes the query to SQL-Server and then takes the resultset and sends it to the quepub1.htx file that will format the results into a HTML page and give it to the Web server to return it to the client browser. The .HTX file that is being called by this example is in Listing 21.5.

Listing 21.5quepub1.htx Template File Used in the Creation of a Return Page that Contains the Requested Data <HTML> <HEAD><TITLE>Authors and YTD Sales</TITLE></HEAD> <BODY BACKGROUND="/samples/images/backgrnd.gif"> <BODY BGCOLOR="FFFFFF"> <OBJECT ID="ieList" WIDTH=350 HEIGHT=80 CLASSID="CLSID:8BD21D20-EC42-11CE-9E0D-00AA006002F3"> <PARAM NAME="ScrollBars" VALUE="3"> <PARAM NAME="DisplayStyle" VALUE="2"> <PARAM NAME="Size" VALUE="5151;811"> <PARAM NAME="MatchEntry" VALUE="0"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <br> <br> <%http_all_http%> <br>

<!-The table is not needed for a floating frame but I used it to provide the frame with a more distinctive border --> <TABLE WIDTH=500 HEIGHT=300 BORDER=5> <TR WIDTH=600><TD> <!-This is what creates the floating frame. I used fixed pixels for width and height so that the frame would fit the table exactly. If you want the frame to size proportionatly to the browser winf, don't use a table and specify the width and height parameters with percentages: Width=80% --> <FRAME WIDTH=500 HEIGHT=300 ID= "FLOATER" SRC="foo.htm"> </TD></TR> </Table> <%QUERY_STRING%> <Script Language="VBScript" OnLoad> <%begindetail%> ieList.addItem "<%au_fname%>" & " " & "<%au_lname%>" & ":" & "< %au_id%>" <%enddetail%> Sub ielist_click Dim buffer Buffer = "http://iymalluf.rt66.com/eftproot/QuePub2.idc? authid=" & right(ieList.List(ielist.listindex),11) Floater.Location = buffer End Sub </Script> </BODY> </HTML> The key part of this .HTX listing is between the %begindetail%...%enddetail% pair. These two keywords constitute a loop that will iterate through all of the rows returned in the recordset. In this application, the authors first and last names will be added to a dropdown list on the returned Web page. Finally, the HTML page that calls all of this is presented in Listing 21.6.

Listing 21.6datacc1.htm Initial HTML File that Accepts the Query Parameters and Requests Data from the Server <HTML> <HEAD> <TITLE>VBS Query1</TITLE> </HEAD> Enter search criteria in either the First Name or Last Name Boxes Standard SQL Server Wild Cards are accepted. <br> "First Name" <Input type=text id=txtFName Value=""> "Last name" <Input type=text id=txtLName Value=""> <br><br> <input type=button name="btnGetData" Value="Click to Send Query"> <BODY> <script Language="VBScript"> <!-Dim MyQuery Sub btnGetData_OnClick Location = "Quepub1.idc?fname=" & FixEntry(txtFName.Value) _ & "&lname=" & FixEntry(txtLName.Value) End sub Function FixEntry(MyText) Dim lngStart Dim lngEnd Dim Buffer lngStart = 1 Do While lngStart > 0 lngEnd = Instr(lngStart, MyText, "%") If lngEnd > 0 then Buffer = Buffer & Mid(mytext, lngStart, lngEnd - lngStart) Buffer = Buffer & "%25" lngStart = lngEnd + 1 Else if len(buffer)>0 then buffer=buffer & right(mytext,len(mytext)-lngstart+1) End if lngstart = 0 End If Loop If len(myText) = 0 then buffer = "%25" If len(buffer) > 0 then

FixEntry = buffer Else FixEntry = MyText End If End Function --> </script> </BODY> </HTML> Listing 21.6 is a simple form that allows the user to enter any characters into the text boxes and then submits that data to the .IDX file. To try this application, type in a character or two with a trailing %. This is SQL Servers wildcard character. In Listing 21.6, you will find a VBScript procedure called FixEntry(). The purpose of this function is to search the string passed to it for any % wildcard characters, strip them out, and replace them with an HTML equivalent that can be passed through an HTML argument to a server. The resulting Web page from this document is illustrated in Figure 21.3. FIG. 21.3 The DacAcc1.htm screen looks like this. In the example in Figure 21.3, let's run a query that will accept any first name, by using only a % character in the first name field and any last name that starts with Gr by entering Gr% into the last name field. Press the click to send query button, and the two parameter fields are sent to the Microsoft Internet Information Servers IDC component. Using the quepub1.idc and quepub1.htx files along with these parameters produces the Web page illustrated in Figure 21.4. FIG. 21.4 This Web page results from the datacc1.htm to quepub1.idc to quepub1.htx interaction. The page you see in Figure 21.4 is the result of the quepub1.htx file (refer to Listing 21.5) being fed data from the rowset created through the quepub1.idc file (refer to Listing 21.4). We used an ActiveX ListBox as the container for the data being returned so that users could scroll through the list and easily select the author they seek from the resultset returned. Listing 21.7quepub1.htx Setting up the HTX Code to Load Data into an ActiveX Control

<Script Language="VBScript" OnLoad> <%begindetail%> ieList.addItem "<%au_fname%>" & " " & "<%au_lname%>" & ":" & "<

%au_id%>" <%enddetail%> Notice how the section of HTX code shown in Listing 21.7 is converted to a final output source file shown in Listing 21.8

Listing 21.8 View Source of Query: The Resulting Source Code from the quepub1.htx Showing the ieList additem Detail <Script Language="VBScript" OnLoad> ieList.addItem "Marjorie" & " " & "Green" & ":" & "213-46-8915" ieList.addItem "Morningstar" & " " & "Greene" & ":" & "527-723246" ieList.addItem "Burt" & " " & "Gringlesby" & ":" & "472-272349" This is just a simple example of what can be done. With a little imagination, you can create very complex result pages, complete with whatever formatting is needed. Included with this page being returned is not only the ListBox loaded with the query results but also a floating frame. A dummy page is loaded into it initially, so that the frame can accept other documents being loaded into it later. When a user clicks on one of the authors returned in the ListBox, another query is called. The click event of the ListBox is used to send another query to the IDC containing the au_id data from the list box. That click event is shown in Listing 21.9. Listing 21.9quepub1.htx The Click Event of the List Box Calling Another Query and Targeting it into the Floating Frame

Sub ielist_click Dim buffer Buffer = "http://iymalluf.rt66.com/eftproot/QuePub2.idc? authid=" _ & right(ieList.List(ielist.listindex),11) Floater.Location = buffer End Sub All we had to do was create a string that included the file path to the .IDC file, a question mark character, and the expected parameter for this query. Continuing with this example, click the Marjorie Green data row, and the resulting parameter is sent to the quepub2.idc file through the

MIIS. That file is shown in Listing 21.10, which includes a three-table join. Listing 21.10quepub2.idc The Qupub2.idc File with the Three-Table Join

Datasource: Publishers Username: sa Template: quepub2.htx SQLStatement: +SELECT titles.*,titleauthor.*,Authors.* +FROM titles LEFT JOIN titleauthor +ON titles.title_id = titleauthor.title_id +LEFT JOIN authors +ON titleauthor.au_id = authors.au_id +Where authors.au_id ='%authid%' By now you are probably beginning to see that the .IDC files are fairly straightforward, requiring only a datasource, username, template path, and the query that requests rows from the database. The quepub2.idc, while simple, returns many columns of data. In the .HTX file shown in Listing 21.11, we added a few extras besides just the returning of rows. Listing 21.11quepub2.htx The Template File with Additional HTTP Variable Information

<HTML> <HEAD><TITLE>Authors and YTD Sales</TITLE></HEAD> <BODY BACKGROUND="/samples/images/backgrnd.gif"> <BODY BGCOLOR="FFFFFF"> <%QUERY_STRING%> <%ALL_HTTP%> <br> <hr> <%begindetail%> TITLE: <%title%> <br> TYPE: <%type%> <br> PRICE: <%price%> <br> PUBLISHED: <%pubdate%>

<br> YTD SALES: <%ytd_sales%> <br> NOTES: <%notes%> <hr> <br> <%enddetail%> <%IF CurrentRecord EQ 0%> There are no publications matching this author <%EndIf%> <Script Language="VBScript"> </Script> </BODY> </HTML> In the first part of Listing 21.11, we use two variables that are not part of the rowset returned. The <% Query_String%> variable returns the parameters sent to the .IDC file by the client page, in this case quepub1.htx. The <%ALL_HTTP%> variable returns all of the known information about the current transaction, including the server address, the client address, the client browser, and other useful information detailed in Table 21.3. Clicking on any name in the ListBox causes the floating frame to be filled with the data related to the author selected. Figure 21.5 shows the result of clicking a name. FIG. 21.5 The author information is loaded into the floating frame.

From Here...
The subject of the Miscrosoft Internet Information Servers Internet Database Connector could take a whole book by itself. The intention here was to give you an idea of what can be done using the IDC to build Web pages during runtime on the server side that included VBScript as part of the package. If anything this chapter hopefully gives you some ideas of your own to try out. You can build very sophisticated VBScript based template files using the IDC.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 22 - VBScript Language Elements


by Ron Schwarz

In this chapter
q q q q

q q q q

Language features Various language elements make up VBScript. Programming elements by group Programming elements are grouped by category. Learn which statements and functions work together. Tying it all together Learn to use different parts of the language with each other. Make the language work for you Use this chapter as a roadmap to the parts of this book that focus on specific parts of the VBScript language. Copious cross-references make it easy.

This chapter describes VBScript language features. If you're familiar with Visual Basic, you can use this chapter, as well as Chapter 13, "Comparing VBScript, VBA, and Visual Basic," to apprise yourself of the differences you'll run into with VBScript. Many of the language elements named in this chapter are discussed in-depth in other chapters (references to these are provided) and are therefore given light coverage here. If you're new to Visual Basic programming in general, this chapter will give you a good understanding of the language and capabilities of VB/VBS code. Other chapters in this book focus on structural aspects of scripting and event handling, specific language topics, visual program design using the ActiveX Control Pad and HTML Layout features, and other programming issues; this chapter covers the language and syntax as a whole, and points you to places in the book where specific features are discussed in-depth. Language elements are covered in groups of topically related methods, statements functions, and keywords. This chapter is more of a guide than a reference; it presents each group of language features in the context of similar related features, and the groups are presented in order of typical frequency of use.

Each section contains a table listing related features (with a short description of each) and tutorial information describing the commonly used language elements in each category.

Declaration and Array Handling


VBScript contains a variety of language elements pertaining to variable and procedure declarations, and array handling. Table 22.1 lists them. Table 22.1 Declaration and Array Handling Elements Keyword Sub Function Public Private Dim ReDim Erase IsArray Lbound Ubound Description Declaration keyword for Sub procedures Declaration keyword for Function procedures Declares a variable or array to be available to all procedures regardless of where it is declared Declares a variable or array to be local to the script in which it is declared Declares a variable or array; scope is determined by placement of Dim statement Resizes an array; can only be used with dynamic arrays Clears contents of an array Reports whether a variable is or is not an array Returns lowest element of an array (Always 0 in VBScript) Returns highest element of an array

Option Explicit Requires all variables to be declared before they can be used

See Chapter 15, "VBScript Data Types and Variables," for further discussion of arrays. See Chapter 19, "VBScript Procedures," for in-depth coverage of declaration and procedure calling issues.

Option
Unlike Visual Basic (which provides options for array base subscript, string comparison modes, and variable declaration scope), the only option implemented in VBScript is Option Explicit. When

Option Explicit is selected, a variable must be declared before it can be used, or an error will occur. When Option Explicit is not used, a variable will be automatically created the first time it is referenced. (This does not apply to arrays, however; they must be explicitly dimensioned prior to use, regardless of Option Explicit settings.) To use Option Explicit, simply place it as the first statement in your script, before any code or procedures. While it may seem tempting to avoid using Option Explicit, it's recommended that you include it in anything beyond the simplest of scripts. The safety net it provides more than compensates for the slight inconvenience of having to explicitly declare each variable before use. Remember, VBScript doesn't have the sophisticated analysis and debugging tools that makes Visual Basic development so effortless; with VBScript you need every advantage you can get. Being able to flag bugs caused by simple typos in variable names can save you hours of grief in a single project, and Option Explicit provides that ability.

Procedure Declarations
Sub and Function are used to declare Sub procedures and Functions. A Sub procedure is a block of code that is invoked by using its name (as if it were a built-in statement, or method) and following it with any parameters that are declared in the actual Sub. To declare a Sub procedure, use this syntax: Sub ProcedureName (Arg1, Arg2, Arg3, ...) A procedure named ChangeURL, which accepted one argument named NewURL, would be declared as: Sub ChangeURL (NewURL) To invoke it and pass it a value of "www.microsoft.com", you'd use: ChangeURL "www.microsoft.com" A complete routine might look like Listing 22.1. Listing 22.1 Example Sub Procedure Invocation Sub ChangeURL (NewURL) NewURL = Trim(NewURL) If NewURL = "" then Exit Sub Else

Location.href = "HTTP://" & NewUrl Endif End Sub In the example in Listing 22.1, we first use Trim to remove any leading and trailing spaces from the NewURL variable. Then we test to see if it's got anything left in it. If the result is "" (an empty string), we exit the Sub procedure. If the variable is greater than an empty string, we create a new .href for the Location object by combining the "HTTP://" prefix with the contents of NewURL. The Sub procedure ends with an "End Sub" statement. While you normally invoke a Sub procedure by typing its name and any required arguments (separated by commas), you may encounter an alternate syntax. The Call statement can be used, in this form: Call AnySubProcedure (arg1, arg2, arg3) The main difference here (apart from the actual inclusion of the Call keyword, of course) is the fact that the argument list must be surrounded by parentheses. When invoking a Sub procedure without the Call statement, you cannot use the parentheses. (The Call syntax is included for backward compatibility with versions of the BASIC language that predate the current procedure-name-only invocation style.) Functions are declared in a similar manner as Sub procedures: Function FunctionName (Arg1, Arg2, Arg3, ...) Invoking a Function is a bit different, however; unlike a Sub procedure, a Function returns a value in its name. Here's a typical Function procedure: Function BuildURL (NewURL) BuildURL = "HTTP://" & NewUrl End Function In this example, we build a URL by passing an address to the function and returning "HTTP://" with the address concatenated. To return the value, we assign it to the function, just as if we were assigning it to a variable. We can combine the preceding two examples and use a Sub and Function procedure to modularize our code, as shown in Listing 22.2. Listing 22.2 Using Sub and Function Procedures

Sub ChangeURL (NewURL) NewURL = Trim(NewURL) If NewURL = "" then Exit Sub Else Location.href = BuildURL (NewUrl) Endif End Sub Function BuildURL (NewURL) BuildURL = "HTTP://" & NewUrl End Function The ChangeURL Sub procedure in Listing 22.2 calls BuildURL and passes the result to the Location. href property. The code is invoked exactly as in the prior ChangeURL example: ChangeURL "www.microsoft.com"

Variable Declarations
Three keywords deal with variable declaration: Dim, Public, and Private. Once a variable is declared, the result is identical. The only difference is scope. (Scope determines in which context(s) a variable will exist.) When declared Public, a variable will be available in all procedures. When declared Private, it will be limited to the script in which it appears. When declared with Dim, scope is determined by context; if you Dim a variable at the script level (outside a procedure), it will be available to all procedures in that script. If you Dim it within a procedure, it will be local to that procedure. Here's an example of the three forms of variable declaration: <SCRIPT LANGUAGE=VBScript> Public UserName Private Tally Sub RefreshInfo Dim ItemCount ... The Public UserName variable will be available in all scripts, the Private Tally variable will only be available in the script in which it's used, and the ItemCount variable will only be available in the RefreshInfo procedure.

As this book goes to press, Public and Private keywords are documented but not yet

implemented in the pre-release version of Internet Explorer that is available for testing.

Array Declarations
Arrays are lists of variables. They are created with the same three declaration keywords as variables and are subject to the same scoping rules. Here is a typical array declaration: Dim Age(10) This creates an array named Age, with 11 elements (arrays begin with 0). To access a specific element of an array, use it as you would any other variable but include its subscript in parentheses; for example, Age(5) = YourAge will assign the value in the variable named YourAge to element 5 of the Age array. You can create multidimensional arrays. Dim Phone(100, 4) will create an array with 101 elements and 5 subelements. For each subscript of the first part, you will be able to have 5 subelements (remember, the first element is 0). So, Phone(1,3) will return the fourth phone number for the second "record". The ReDim keyword can be used to change the size of an array after it's created. There are a couple of caveats:
q

You can't change the number of dimensions. (For example, you can't change Phone(100,4) to Phone(100).) You can only redimension a dynamic array. (A dynamic array is dimensioned with empty parentheses like Dim Users(). An array declared with a specific number is known as a static array; it can't be fully erased, or resized.) Before you can use a dynamic array for the first time, you have to ReDim it.

ReDim uses the same syntax as Dim. It does have one option, however. You can use the Preserve keyword to retain any preexisting contents of the array. (If you make the array smaller, of course, you'll lose anything in the elements that are removed.) To increase the size of an array named Count by 10, you'd use this code: ReDim Count(Ubound(Count) + 10) Preserve The Ubound function returns the number of the highest subscript in an array. So if the array was previously ReDimmed to 100, Ubound(Count) would return 100, and Ubound(Count) + 10 would equal 110, which is what the array would be ReDimmed to in this example.

VBScript also has an Lbound function, which returns the lowest subscript in an array. However, since all VBScript arrays begin with element 0, it's not of much use.

You can remove a dynamic array with the Erase statement. The following syntax demonstrates how to create and erase a dynamic array: Dim ScratchVars() ReDim ScratchVars(25) Erase ScratchVars You can use Erase with static arrays; however, it won't remove the arrayit will only clear the contents of the elements it contains. The IsArray function will return True if tested with a variable name, so IsArray(NameList) will return True if NameList is an array and False if it's a simple variable.

Comments
Comments are not executed. They are only for human eyes. By commenting your code, you make it easier to understand when you look at it later on. While it's easy to understand your code as you write it, it's amazingly easy to forget what's going on a month or two later when you revisit it. You can place comments in your code by using either Rem or [sp] (see Table 22.2). Table 22.2 Comments Keyword Description Rem ' Used at beginning of line to create comment ("Remark") Used anywhere in line, everything beyond is comment

Rem is generally used when entering comments alone on a line, and [sp] is used when placing comments at the end of a line of code. (Rem is shorthand for remark.) Both are shown in the following example: Rem This routine accepts a number and adds it to the running tally. For C = 1 to Total 'Count through the list The first line is a comment; it has no executable code. The second line consists of a line of code with

a comment appended to the end.

Constants
Unlike Visual Basic, VBScript doesn't provide a way to use true Constants. If you need to define a constant, you'll have to use a variable as a pseudo-constant and be very careful to avoid changing it in code. There are, however, some built-in constants, such as True and False, and the Empty, Nothing, and Null keywords which exhibit constant-like behavior. True and False contain the values -1 and 0, respectively. They're used when you're testing conditions returned by expressions and various functions. (Throughout this book, you'll see frequent reference to True and False as returned values.) Empty is a special value used with variables. An Empty variable is one that has been created, but not yet assigned a value. With a numeric value, it is 0; with strings, it's "". Null is another type of special value. It indicates that the variable is not valid. It is not equal to any value, therefore, it's not equal to 0 in a numeric variable nor is it equal to "" in a string. If any part of an expression is Null, the Null will propagate throughout the expression, and the result will be Null. Nothing removes an object reference. If you create an object reference with Set Handy=LongFormName.LongControlName you'll be able to refer to LongFormName.LongControlName properties by using the Handy.Property format. To remove the Handy reference, use Set Handy=Nothing

Assignment
VBScript Assignment Operators are listed in Table 22.3. (The equals sign (=) and the Let keyword are fully discussed in Chapter 16, "VBScript Operators", in the "Equality" section.) Table 22.3 Assignment Operators Keyword Description = Let Set Assigns an expression to a variable Obsolete statement used at start of assignment Creates an Object Reference; useful for creating shortcuts to items in the Internet Explorer object hierarchy

Set can be used to assign an object to a variable. The example in Listing 22.3 demonstrates one use of the Set keyword.

Listing 22.3 set.htmExample of Set Operator <HTML> <TITLE>Set Example</TITLE> <p> <FORM NAME="LongFormName"> <INPUT TYPE="TEXT" NAME="LongControlName" SIZE="10"> </FORM> <SCRIPT language="VBScript"> Sub Window_OnLoad Set Handy=LongFormName.LongControlName Handy.Value="It Works!" End Sub </SCRIPT> </HTML> In Listing 22.3, a Form named LongFormName contains a Text control named LongControlName. To access the control's Value property, you can either use LongFormName.LongControlName.Value or use Set to assign a it to a variable. After the Set statement above creates the variable Handy, you can use it instead of the longer LongFormName.LongControlName, as demonstrated in the example. YIt's important to note that you're not creating a new instance of the original object; you're simply assigning a type of alias to it. When you use the variable named Handy in the example, you're really using the actual control in LongFormName.LongControlName. When you run the example, you'll see It works! in the Text control, indicating that by setting Handy.Value, you're really working with the control.

String Handling
Microsoft's Basic language implementations have always been noted for a rich set of string handling features. VBScript carries on with this tradition. Table 22.4 lists the string handling functions implemented in VBScript. Table 22.4 String Handling Functions Function Description

Asc, AscB, AscW Returns the ASCII value of the first character in the string being evaluated

Chr, ChrB, ChrW Returns a one-character string representing the numeric value being evaluated Instr, InStrB, Len, LenB LCase UCase Left, LeftB Right, RightB Mid, MidB Space String Ltrim Rtrim Trim CStr StrComp Returns the position of a search string within a target string Returns the length of a string Returns a lowercase representation of a string Returns an uppercase representation of a string Returns a specified number of leftmost characters in a string Returns a specified number of rightmost characters in a string Returns a specified number of characters from a specified position in a string Returns a string containing a specified series of space characters Returns a string containing a specified series of any specified character Returns a string which is a copy of the target string, with all leading spaces removed Returns a string which is a copy of the target string, with all trailing spaces removed Returns a string which is a copy of the target string, with all leading and trailing spaces removed Converts number to string Performs a case-sensitive, or case-insensitive comparison on two strings

Some string functions end with B or W. These functions are byte and wide equivalents for the corresponding functions without a suffixed letter. For instance, Len returns the length of a string in characters, but LenB returns the length in bytes. Asc returns a numeric value of a character, and AscW returns the numeric value of a Unicode character.

You'll probably be using the string handling functions extensively in your scripting work.

Asc and Chr


Asc and Chr are the inverse of each other. Asc returns the ASCII numeric value of a one-character string, and Chr returns a one-character string representing a numeric ASCII value. (ASCII means American Standard Code for Information Interchange.) The syntax for Asc is NumericValue = Asc("A"), which would return 65. StringValue = Chr(65) would return "A".

Instr
To search a string for a sub-string, use the Instr function: Source = "This is a test" Search = "test" Found = Instr(Source, Search) Found will contain the position of Search within Source. So if Source contains "This is a test", and Search contains "test" Found will contain 11.

As this book goes to press, Microsoft documents a third optional parameter for Instr. If Found = Instr(Source, Search, 1) is used, the test will be case-insignificant. However, this option was not functional with the preliminary versions of software available for testing.

Len
The Len function returns the length of a string. The syntax is this: StringLength = Len(TestString)

LCase and UCase


LCase and UCase are used to respectively return a lowercase or uppercase representation of a target string. So, UCase("fubar") will return FUBAR.

Left and Right


Left and Right will return a specified number of the leftmost or rightmost characters of a string. For example, Left(Source, 10) will return the first 10 characters of Source.

Mid
If you're a Visual Basic programmer, you know that Mid is unique in that it can be used as a function or a statement. VBScript, however, only provides the Function implementation of Mid.

Mid returns a specified numbers of characters of a string, just like Left and Right; however, unlike those functions, it accepts a starting position. So, Fragment = Mid(Source, 5, 2) will return the two characters starting with the fifth character of Source.

Space
Space returns a string containing the specified number of space characters. Space(10) returns a string consisting of ten spaces.

String
String is similar to Space, but it allows you to specify which character to return. You supply a string or a literal, and a number. So, String(25, "*") will return a string consisting of 25 "*" characters. You can alternatively supply an ASCII number instead of a string for the second argument. In that case, String(10, 32) will return ten spaces. (32 is the ASCII code for the space character.)

Ltrim, Rtrim, and Trim


Ltrim, Rtrim, and Trim remove leading, trailing, or leading and trailing spaces from a string. Ltrim (User) will return the contents of User, with any leading spaces removed. Rtrim works the same way for trailing spaces, and Trim removes leading and trailing spaces.

CStr
CStr returns a string representation of a number. CStr(5) will return a string containing "5". CStr is aware of international conversion issues, such as different style decimal separators. Additionally, it will convert Boolean (True/False), Date, and Error values to strings.

StrComp
StrComp is used to compare one string against another. If you know that both strings being compared are of the same case, you can simply use an equal sign to compare. Thus, if String1 = "Cantaloupe" and String2 = "CANTALOUPE", testing If String1 = String2 will fail. StrComp can be used to perform case-significant or case-insignificant tests, by using the syntax: Test = StrComp(String1, String2, CompareMode). If CompareMode is 0 (or, if CompareMode is absent) the test will be casesignificant, just like an equal sign test. But if CompareMode is 1, the test will be case-insignificant.

Control Flow Statements


Table 22.5 presents the control flow statements and their descriptions. Table 22.5 Control Flow Statements

Statement Do...Loop For...Next Select Case

Description Executes code block while or until a test condition is met Executes code block a specified number of times Tests for multiple conditions, executes corresponding Space blocks of code

While...Wend Executes code block while test condition is met If...Then...Else Executes code block(s) depending on results of test

Variant Management/SubTypes
Table 22.6 shows the various variant subtypes. Table 22.6 Variant Subtypes Subtype IsArray IsDate IsEmpty IsNull IsObject VarType Description Tests if subtype of variable is Array Tests if variable or expression returns a Date Tests if variable is uninitialized Tests if variable is initialized, but does not contain data Tests if variable refers an OLE automation object Returns a String containing the subtype of a specified variable

IsNumeric Tests if variable or expression returns a valid number

VBScript does not have true variable typing; all variables are of the Variant type. However, Variants can contain any variable type as a subtype. Whenever a type (such as String, Date, and so on) is mentioned, it should be understood to refer to a Variant subtype (see Table 22.6).

See "The Variant's Data Sub-Types," for a full discussion of data types and programming issues. [Chapter 15, "VBScript Data Types and Variables"] See "What Is an Object," for more information about object usage. [Chapter 11, "Designing VBScript Applications"]

Math Functions

The math functions provide a variety of trigonometric, logarithmic, and other mathematical capabilities. Table 22.7 lists these functions. Table 22.7 Math Functions Function Atn Cos Sin Tan Exp Log Sqr Rnd Description Returns the arctangent of a number or expression Returns the cosine of a number or expression Returns the sine of a number or expression Returns the tangent of a number or expression Returns e raised to a power from a number or expression Returns the natural (base e) logarithm of a number or expression Returns the square root of a number or expression Returns a random number

Randomize Seeds the random number generator

The Atn, Cos, Sin, and Tan trigonometric functions all use the same simple syntax (keyword (number)) to return their respective value: Atn(35) The Exp and Log logarithmic functions also use that syntax to return their results, as does the Sqr square root function. Randomize and Rnd are used for seeding the random number generator and for generating a random number. Using Randomize by itself causes the random number generator to be seeded with the current value in the system timer. You can also place a number or numeric argument after Randomize and use that value as a seed, such as Randomize 7365. To retrieve a random number, use this syntax: RandomNumber = Rnd The variable (in this case, RandomNumber) will contain a random number within the range of 01. The Rnd function will accept a number as an optional argument. If you supply one, the following rules are used:
q q q

< 0 Always returns the same value, seeded by the supplied number > 0 The next random number in the sequence created by the random number generator 0 The last random number created by the random number generator

Random Number Trivia The numbers returned by the random number generator (a built-in part of VBScript) are not truly random. Technically, they are referred to as pseudo-random numbers. Each time the random number generator is started, it produces a sequence of random numbers. By using Rnd with a negative argument one time before calling Randomize with a seed, you can produce identical "runs" of pseudo-random numbers. (Remember to use the same seed value for Randomize each time too when doing this.) Even though the number returned by Rnd is limited to the range of 01, you can convert this to other ranges. By using the formula Int((HighRange LowRange + 1) * Rnd + LowRange), you can produce random numbers in any range. (Assign your lowest and highest desired numbers to LowRange and HighRange before calling this formula, and it will return a result in the desired range.) The following expression returns a random number between 10 and 20: Int((20 - 11) * Rnd + 10)

Date and Time Functions


VBScript has a wealth of Date and Time functions. Table 22.8 lists those functions. Table 22.8 Date and Time Functions Function Now CDate Date DateSerial DateValue Day Month Description Returns the current Date and Time Returns a Date type representation of a number or expression Returns the current Date Returns a Date type variable (containing the date) representing the Date of a specified Year, Month, and Day Returns a Date type variable(containing the date) from a string variable or expression containing text representing a date Returns the day of month for a specified date Returns the number of the month for a specified date

Weekday Year Time TimeSerial TimeValue Hour Minute Second

Returns a number representing the day of the week for a specified date (1 = Sunday, 2 = Monday, and so on) Returns the year part of a specified date Returns the current Time Returns a Date type variable (containing the time) when provided a specfied time in parameters containing the hour, minute, and second Returns a Date type variable (containing the time) from a string variable or expression containing text representing a time Returns a number representing the Hour of a specified time Returns a number representing the Minute of a specified time Returns a number representing the Second of a specified time

Date returns the current date as a string in the form of 1/1/97. Time likewise returns the current time, in the form of a string like 12:00:00 PM. Now returns both date and time in one string, such as 1/1/97 12:00:00 PM. All three of these functions are used without arguments. Like all functions, you can assign them anywhere it's legal to accept a value, such as a variable or the Value property of a Text control. DateSerial returns a Date sub-typed variant when passed three arguments (for Year, Month, and Day). DateSerial(1997, 1, 1) will return a variable containing the date for 1/1/97. You can do simple date math by adding (or subtracting) a value to any of these three parameters. So, DateSerial(1997, 1 5, 3) will return 8/3/96. DateValue also returns a Date sub-typed variant, but it accepts a single string, using many common date formats, such as 4/16/1975 and 11/16/76. It can also recognize text representations of dates, such as October 23, 1949 (common abbreviations such as Oct are also accepted). TimeSerial is identical in use to DateSerial, but using Hour, Minute, and Second in place of Year, Month, and Date. It returns a variable containing the time represented by the combined parameters. TimeValue is likewise identical in form to DateValue but accepting common time formats (such as 8:00PM or 20:00) in its single parameter. It returns a variable containing the time as interpreted from the string supplied in the parameter. Year, Month, and Day return their respective values when passed a Date. You can use common forms of date, so Year("Dec 25, 1997") will return 1997, for instance. Hour, Minute, and Second are the time counterparts to the Year, Month, and Day functions, and use the same syntax. They return their respective values when passed any valid time in their parameter.

Conversion Functions

In VBScript, all variables are of Variant type. A variant can hold any type of data. VBScript assigns a subtype to a variant depending on content, context, and by using conversion functions (listed in Table 22.9). In most cases, conversion is automatic and transparent. When you want to override the settings created by the content of a variable, or the context in which it is assigned a value, you can use the conversion functions. Table 22.9 Conversion Functions Function Abs Asc Chr CBool CByte CDate CDbl CInt CLng CSng CStr Description Returns the Absolute value of a number or expression (Described in String Functions) (Described in String Functions) Evaluates an expression and returns either True or False (if non-zero, True; otherwise, False) Returns a Byte type representation of a number or expression (Described in Date and Time Functions) Returns a Double precision type representation of a number or expression Returns an Integer type representation of a number or expression Returns a Long type representation of a number or expression Returns a Single precision type representation of a number or expression (Described in String Functions)

DateSerial (Described in Date and Time Functions) DateValue (Described in Date and Time Functions) Fix Same as Int for positive values, but returns next lower whole negative number for negative values Returns a String containing a Hexadecimal (base 16) representation of a specified number or expression (the opposite can be accomplished by prefixing a hex number with &H; for instance, &HFF equals 255) Returns next lower whole number value for positive values, next higher whole negative number for negative values Returns a String containing an Octal (base 8) representation of a specified number or expression (the opposite can be accomplished by prefixing a hex number with &O (that is the letter O, not a zero); in other words, &O77 equals 63 decimal) Returns the sign of a number or expression; 1 if positive value, -1 if negative value

Hex

Int

Oct Sgn

TimeSerial (Described in Date and Time Functions) TimeValue (Described in Date and Time Functions) Int, CInt, and Fix are related functions that return integers. For positive numbers, Int and Fix round

down to the next lowest integer, and CInt rounds up. For negative numbers, CInt and Fix round up toward zero, and Int rounds down to the next highest negative number. (So, CInt(-1.6) returns -2, but Fix(-1.6) returns -1, while Int(-1.4) returns -2, and Fix(-1.4) returns -1.) Abs returns the Absolute Value (the number without its sign) of a variable. Abs(1.23) and Abs(-1.23) will both return 1.23. CBool, CByte, CDbl, CLng, and CSng convert a number to their respective sub-types as described in Table 22.9. They all use the Result = Keyword(Value) syntax. So, in the expression Answer = CBool ("True"), Answer will contain -1. Hex and Oct return strings containing Hexadecimal and Octal equivalents for decimal arguments. Hex (255) returns FF, and Oct(255) returns 377 (&hff and &o377 both return 255, as described in Table 22.9). The Sgn function accepts a single argument and returns either 1 or -1 depending on the sign of the value passed. Sgn(25) will return 1, and Sgn(-25) will return -1.

Input/Output
The two built-in modal dialogsInputBox and MsgBox (see Table 22.10)are useful for times when you need to either notify the user of something out of the ordinary or to obtain a short bit of information via keyboard input.

Modal means that the rest of the application is suspended while the dialog is visible.

Table 22.10 Input/Output Keyword Description MsgBox Displays short message and optionally returns a value indicating which of a series of buttons was clicked

InputBox Accepts text entry and returns it as a String value

MsgBox
MsgBox creates a MessageBox and takes two forms: it can be used as a statement or as a function. In its simplest form, it takes a single string argument and waits until OK is clicked. The following

statement: MsgBox "Click me!" will result in a MessageBox with Visual Basic in the title bar, Click me! in the center, and a single button labeled OK. The underlying script that invokes the MessageBox will pause until the user clicks OK. MsgBox can also be used as a function. When placed on the right side of an equal sign, it will return a value to the variable on the left side. When used as a function, the parameters have to be enclosed in parentheses, as is the case with all function calls. Optional parameters are available for Buttons, Title, HelpFile, and HelpContext. (For information on creating your own Windows help files, see Que's Designing Windows Help Systems.) This is the MsgBox syntax: MsgBox(Prompt, Buttons, Title, Helpfile, HelpContext) This is a typical invocation of the MsgBox function: Value = MsgBox("Click me!", 4, "A Test", "C:\MyDir\MyApp.hlp", 123) Figure 22.1 shows the MsgBox the above expression creates. Whatever you enter for the Title parameter will appear on top of the MessageBox when it's displayed. It's similar to a form's Caption property in Visual Basic. Using the Buttons parameter can be a bit tricky. The number you enter determines how many buttons are displayed, how they're labeled, which (if any) icon is displayed on the MessageBox, the default button, and the level of modality. The following tables (22.11 through 22.14) will help you make sense of it. FIG. 22.1 A MsgBox. Table 22.11 MessageBox Button Options: Buttons Value Button(s) 0 1 OK OK, Cancel

2 3 4 5

Abort, Retry, Ignore Yes, No, Cancel Yes, No Retry, Cancel

If the value of the Button parameter is 0, or if it's missing, only the OK button will be displayed. Otherwise, the five other options are available. Table 22.12 MessageBox Button Options: Icons Value Icon 16 32 48 64 Critical Message (red circle/"X") Warning Query (Question Mark) Warning Message (Exclamation Mark) Information Message (Small "i")

When the Button value is 0, or is missing, no icon will be displayed. Table 22.13 MessageBox Button Options: Defaults Value Default Button 0 256 512 768 First Second Third Fourth

When only one button is displayed, it will be the default. Table 22.14 MessageBox Button Options: Modality Value Modality 0 Application (Internet Explorer is suspended while MessageBox is displayed) 4096 System (All applications are suspended while MessageBox is displayed)

System modality is essentially imaginary in 32-bit Windows. It's accepted as part of the API

but has no modal effect. Other programs can continue to be accessed, even thought the system modal flag is set. It will, however, be an "always on top" window, which means that even though you can continue to interact with other applications, the system-modal MessageBox will always float on top of any other windows on your screen.

You may be wondering how to combine this mess of information spread over several tables into one variable. Actually, it's quite simpleyou just add them all together! Take one selection from each table, add them together, and you'll have all the effects you specified. So, Value = MsgBox("Click me!", 2 + 32 + 256 + 4096) will result in a system-modal MessageBox, with three buttons (Abort, Retry, Ignore), the second (Retry) button as the default, and a question-mark icon. Once you're able to create the type of MessageBox you need, you're most of the way home. The only remaining issue is how to determine which button was clicked after the MsgBox function executes. The answer is always returned by the function, according to Table 22.15. Table 22.15 MsgBox Return Values Value Button 1 2 3 4 5 6 7 OK Cancel Abort Retry Ignore Yes No

If the user presses Enter, the effect will be the same as if the default button was clicked. And pressing Esc will have the same result as clicking Cancel (if present).

InputBox
The InputBox function displays an application-modal dialog and contains a single TextBox that can accept keyboard entry. The syntax is generally similar to MsgBox, with a few differences. Unlike MsgBox, InputBox has no confusing proliferation of numeric options for buttons, icons, and modality. InputBox is pretty straightforward in that regard. The user sees one TextBox, two buttons (OK and Cancel, with OK always the default) and optionally a title and prompt. When OK is clicked, or Enter is pressed, any text contained in the TextBox is returned by the InputBox. When Cancel is clicked, or Esc is pressed, InputBox returns an empty string ("").

In addition to the absence of a Buttons parameter, the InputBox function has Default, Xpos, and Ypos parameters. The syntax for InputBox is this: InputBox(Prompt, Title, Default, Xpos, Ypos, Helpfile, HelpContext) You must have at least the Prompt parameter. All others are optional. If you skip a parameter, you need to include a comma in its place. Also, if you use Xpos, you must use Ypos, and vice versa. Similarly, HelpFile, and HelpContext must also be used with each other. If you want the InputBox to contain any preexisting text when it appears, place the text in the Default parameter. If the Default parameter is absent, the TextBox will be empty when the user first sees it. Xpos and Ypos determine where the InputBox will appear on the user's screen. You can either enter a value in Twips for each of them, or, leave them empty. Xpos determines the distance from the left edge of the screen, and Ypos determines placement relative to the top of the screen. If you do not provide Xpos and Ypos parameters, the InputBox will appear horizontally centered and about 1/3 of the way down from the top of the screen.

A Twip is a typesetting unit of measurement, equal to 1/1440 of an inch.

The following expression creates an input box with a title of Flavor Entry, and a prompt asking Which flavor? If the user just clicks Ok without entering anything, the default value of Vanilla will be returned to the Flavor variable. Flavor = InputBox("Which flavor?", "Flavor Entry", "Vanilla")

Error Object
Error handling in VBScript is a simplified version of that which VB provides. Most of the On Error and Resume options are unimplemented. On Error Resume Next, which forces the code to continue execution when an error occurs, and On Error Goto 0, which turns off error handling, are the only error handling statements. The Error Object contains several properties which are set when an error occurs; testing it after an operation that is suspected of causing an error is your only available means of error trapping.

Operators
Functions and values are useless without a means of assigning, testing, and otherwise accessing them.

VBScript implements a rich set of Operators, which provide the ability to assign, compare, combine, and perform math on variables and expressions. VBScript Operators, (+ - * /\ > < = etc.) are covered in Chapter 16, "VBScript Operators."

Objects
Traditional object management is essentially nonexistent in VBScript. The CreateObject and IsObject keywords are supported, but you cannot create objects when your scripts are used in Internet Explorer, due to security considerations. If you are writing your own script object server (a nontrivial task, unrelated to the subject of Web page automation), you can use these features. You can include objects written in other languages, such as Visual Basic, if they are properly registered. The <OBJECT> tag provides the means for this.

From Here...
VBScript's implementation of the Basic language is very powerful. Even though it's a subset of the full VB language, its features merit attention and study. The following resources will prove invaluable in helping you to learn the language.
q

See Que's Special Edition Using Visual Basic 4, and Visual Basic 4 Expert Solutions, for extensive information on the Visual Basic language. Refer to the Microsoft Visual Basic Scripting Edition Language Reference, for exhaustive syntax descriptions and requirements of all statements, functions, and methods. See Chapter 11, "Designing VBScript Applications," to see how to use the language elements to create script-enabled pages. See Chapter 15, "VBScript Data Types and Variables," for information on variant sub-type issues. See Chapter 16, "VBScript Operators," for coverage of Arithmetic, String, Comparison, and Logical operators. See Chapter 17, "VBScript Control of Flow and Error Handling," which delves into the looping and testing structures, and the Error Object. See Chapter 19, "VBScriptProcedures," for more information on declarations and procedures.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 23 - Microsoft SQL Server 6.5 Web Extensions


by Ibrahim Malluf

Microsoft has embraced the Internet with enthusiasm, as witnessed by the explosion of new products directly targeted at the Internet and by the revamping of existing products to accommodate the Internet. SQL Server is no exception to this drive by Microsoft to place its product line in the forefront of Internet development. Besides the MS Internet Information Server's IDC, which allows for interactive data operations, Microsoft has added a set of extensions to SQL-Server itself that provide a means for easily publishing your data on the Internet. They are called the SQL Server 6.5 Web Extensions. In this chapter, you learn:
q q

q q q q

About the new Web extensions to SQL Server 6.5 These extensions come in the form of three stored procedures; sp_makewebvtask, sp_dropwedtask, and sp_runwebtask. About using the Web Assistant, a new wizard supplied with SQL Server 6.6 The wizard enables you to create static web pages from your SQL Server databases. How to create custom template files for the SQL Server 6.5 Web extensions These extensions include VBScript as part of those templates.

Introducing the SQL Server 6.5 Web Extensions


The core of this Web publishing capability is the addition of three new stored procedures; sp_dropwebtask, sp_makewebtask, and sp_runwebtask. By using these three new stored procedures you can generate HTML Web pages. You can generate these pages on demand, at regular timed intervals, or from triggers designed to react to the changes of critical data. There is even a Web Assistant tool to help you create these pages, which I will discuss later in the chapter. For now let's go over each of these new procedures.

Creating Web Tasks by Using sp_makewebtask

The sp_makewebtask creates a task in SQL Server that makes HTML pages from a set of properties described in the procedures syntax. Listing 23.1 shows this syntax. I am expecting that most of you reading this chapter have a fair knowledge of SQL Server's stored procedure syntax; so I'll just go over the parts that are really HTML page specific. More detailed information is available using the SQL Server's Books Online or the What's New In SQL Server 6.5 manual. The parameter specifications I am showing here come from there. I added additional comments and modifications when I found things to be a little more flexible than described in the original documentation. Listing 23.1 The sp_makewebtask Syntax sp_makewebtask {@outputfile = 'outputfile', @query = 'query'} [, [@fixedfont = fixedfont,] [@bold = bold,] [@italic = italic,] [@colheaders = colheaders,] [@lastupdated = lastupdated,] [@HTMLHeader = HTMLHeader,] [@username = username,] [@dbname = dbname,] [@templatefile = 'templatefile',] [@webpagetitle = 'webpagetitle',] [@resultstitle = 'resultstitle',] [[@URL = 'URL', @reftext = 'reftext'] | [@table_urls = table_urls, @url_query = 'url_query',]] [@whentype = whentype,] [@targetdate = targetdate,] [@targettime = targettime,] [@dayflags = dayflags,] [@numunits = numunits,] [@unittype = unittype,] [@procname = procname, ] [@maketask = maketask,] [@rowcnt = rowcnt,] [@tabborder = tabborder,] [@singlerow = singlerow,] [@blobfmt = blobfmt]] The following list explains the parameters in more detail:
q

@outputfile is the path where the generated HTML file should be stored. This can be a UNC name if the file is to be created on a remote computer. This parameter is required and must be unique for each task created with sp_makewebtask. The outputfile variable is of varchar datatype and has a maximum of 255 characters. @query specifies the query to be run and is a required parameter. The results of the query will be displayed in the HTML document in a table format when the task is run with sp_runwebtask unless your template file uses a different scheme. Multiple SELECT queries can be specified and will result in multiple rowsets returned to the @outputfile. The @query parameter is of text datatype. @colheaders determines whether the query results are displayed with column headers (1) or no column headers (0). Column headers (1) is the default. The colheaders variable is of tinyint datatype. @lastupdated determines whether the generated HTML document displays a Last Updated: timestamp indicating the last updated date and time (1) or no timestamp (0). Timestamp (1) is the default. The timestamp appears one line before the query results in the HTML document.

The lastupdated variable is of tinyint datatype. @HTMLHeader specifies the HTML formatting code for displaying the text contained in the @resultstitle variable. The HTMLHeader variable is of tinyint datatype. These are the values. Value HTML Formatting Code 1 2 3 4 5 6 H1 H2 H3 H4 H5 H6

@templatefile is an optional parameter specifies the path of the template file used to generate the HTML document. This is also where the VBScript programmer can really provide powerful adaptions to the standard output usually generated by SQL Server 6.5. While I am including the description of output here that Microsoft uses, I show you later in the chapter how to bypass the need to display the row data in tables and instead use that data in other ways. The template file contains information about formatting characteristics for HTML documents and contains the tag <%insert_data_here%>, which indicates the position to add the query results in an HTML table. The templatefile variable is of varchar datatype and has a maximum of 255 characters If @templatefile is specified, the following parameters are ignored when the HTML file is generated; @bold, @singlerow, @fixedfont, @tabborder, @HTMLHeader, @table_url, @italic, @URL, @lastupdated, @url_quer, @reftext, @webpagetitl, and @resultstitle. There are two ways to specify the location of the results of a query in a template file: Include the tag <%insert_data_here%>, which indicates the position to add the query results in an HTML table. There are no spaces between the less than sign (<) and the "%i" of %insert and between the "e%" of here% and the greater than sign (>). Specify a complete row format between the keywords <%begindetail%> and <%enddetail%> including <TR>, </TR>, <TD>, and </TD> HTML tags. For each column to display in the results set, include the tag <%insert_data_here%> inside the row format keywords. Specifying the complete row format produces a more precise layout of the results set. When used with this complete row format, @colheaders is ignored. @webpagetitle is the title of the HTML document which is place between the <TITLE>...</ TITLE> tags. The default is SQL Server Web Assistant. The webpagetitle variable is of varchar datatype and has a maximum of 255 characters. @resultstitle specifies the title displayed above the query results in the HTML document. The default title is Query Results. The resultstitle variable is of varchar datatype and has a maximum of 255 characters. @URL provides a hyperlink to another HTML document. The hyperlink is placed after the query results and at the end of the HTML document. This parameter is used to provide links from your document to other documents. If this parameter is specified, @reftext must also be specified, and @table_urls and @url_query cannot be specified. The URL variable is of

varchar datatype and has a maximum of 255 characters. If @table_urls = 1, then @url_query must be included to specify the query to be executed for retrieving hyperlink information, and @URL and @reftext cannot be specified. Information is specified either in @URL and @reftext, or in @url_query and @table_urls. @reftext is the the hyperlink text that describes to what HTML document the hyperlink should take the user. The hyperlink text describes the destination and the hyperlink address comes from the URL in the @URL parameter. The reftext variable is of varchar datatype and has a maximum of 255 characters. @table_urls determines whether hyperlinks are be included on the HTML document and whether the hyperlinks will come from a SELECT statement executed on Microsoft SQL Server. A value of 0 (the default) indicates that there is no query that will generate hyperlinks for the HTML. @URL and @reftext may still be specified for a single hyperlink. A value of 1 indicates that a list of hyperlinks will be created by using @url_query. The table_urls variable is of tinyint datatype. If @table_urls = 1, then @url_query must be included to specify the query to be executed for retrieving hyperlink information, and @URL and @reftext cannot be specified. Information is specified either in @URL and @reftext, or in @url_query and @table_urls. @url_query is the SELECT statement used to create the URL and its hyperlink text. URLs and hyperlink text come from a SQL Server table. With this parameter, it is possible to generate multiple URLs with associated hyperlinks. Use @url_query with @table_urls. The url_query variable is of varchar datatype with a maximum of 255 characters. The url_query variable must return a results set containing two columns: The first column is the address of a hyperlink and the second column describes the hyperlink. The number of hyperlinks inserted into the HTML document equals the number of rows returned by executing @url_query. @whentypen is a required parameter that specifies when to run the task that creates the HTML document. The whentype variable is of tinyint datatype. The possible values are described in Table 23.1.

Table 23.1 The Values and Their Meanings of the @whentypen Parameter Value Description 1 Create page now. The web task will be created, executed immediately, and deleted immediately after execution. This is the default. Create page later. The stored procedure for creating the HTML document will be created immediately, but execution of the web task is deferred until the date and time specified by @targetdate and @targettime (optional). If no @targettime is specified, the web task will be executed at 12:00 a.m. @targetdate is required when @whentype = 2. This web task will be deleted automatically after the targeted date and time has passed.

Create page every n day(s) of the week. The HTML document will be created on day(s) specified in @dayflags and at the time specified by @targettime (optional), beginning with the date in @targetdate. If no @targettime value is specified, the default is 12:00 A.M. The @targetdate parameter is required when @whentype = 3. The day(s) of the week are specified in the @dayflags parameter. More than one day of the week can be specified with the @dayflags parameter. Web tasks created with @whentype = 3 will not be deleted automatically and continue to run on the specified day(s) of the week until the user deletes them by using sp_dropwebtask. Create page every n minutes, hours, days, or weeks. The HTML document is created every n time period beginning with the date and time specified in @targetdate and @targettime (optional). If no @targettime is specified, the Web task will be executed at 12:00 A.M. The @targetdate parameter is required in this case. The task will run automatically every n minutes, hours, days, or weeks as specified by the @numunits and @unittype parameters. The tasks will run until the user deletes them by using sp_dropwebtask. Create page upon request. The procedure is created without automatic scheduling. The user creates a HTML document by running sp_runwebtask and deletes it only by using sp_dropwebtask. Create page now and later. The HTML document is created immediately and re-created according to @whentype = 2. Create page now and every n day(s) of the week. The HTML document is created immediately and re-created according to @whentype = 3, except no @targetdate is required. Create page now and periodically thereafter. The HTML document is created immediately and re-created according to @whentype = 4, except no @targetdate is required. Create page now and upon request. The HTML document is created immediately and recreated according to @whentype = 5. The task must be deleted manually.

6 7 8 9

While not a comprehensive description of the sp_makewebtask, it is enough to get us started with the examples that will be provided later. I would like to make note of the fact that a whentype() other than 1 will result in a task being stored as a repeatable task within your database that will be called according to the specified @whentyen. To remove this task you will need to use the sp_dropwebtask stored procedure or directly delete it from the tasks list.

Using the sp_dropwebtask to Remove Webtasks


The sp_dropwebtask is a much simpler stored procedure than the preceding one. Its purpose is simpler as well. It merely deletes a previously defined Web task that was created by the sp_makewebtask stored procedure. The syntax is shown in Listing 23.2. sp_dropwebtask {@procname = procname | @outputfile = outputfile [ccc]| @procname = procname, @outputfile = outputfile}

Parameter @outputfile

Definition Specifies the name of the web task to be deleted. The outputfile variable is of varchar datatype and has a maximum of 255 characters.

Specifies the name of the web task procedure to delete. The named procedure @procname describes the query for the web task. The procname variable is of varchar datatype and has a maximum of 28 characters.

Using sp_runwebtask to Specifically Run a Previously Created Web Task


sp_runwebtask {@procname = procname | @outputfile = outputfile | Parameter @procname = procname, where @outputfile Definition Specifies the name of the web

@outputfile = outputfile} task to run. The outputfile variable is of varchar datatype and has a maximum of 255 characters. @procname Specifies the name of the web task procedure to run. The named procedure defines the query for the web task. The procname variable is of varchar datatype and has a maximum of 28 characters.

Using the SQL Server Web Assistantfor the Faint of Heart


Does the prospect of directly using the sp_makewebtask stored procedure intimidate you? Relax! The Web Assistant is a wizard-type program that provides a step-by-step interface for creating standard HTML pages from your database. The Web Assistant uses Transact-SQL queries, stored procedures, and extended stored procedures as the foundation for the generated HTML pages. You can let the Web Assistant design an HTML page that includes a table containing all the data in standard table rows for you. The alternative is to provide a template file that contains a custom format for the creation of your HTML pages. Figure 23.1 shows the opening screen of the Web Assistant. In order to use the Web Assistant, you need to have sufficient privileges to create procedures, files, and select privileges on columns. To run Web Assistant double-click the Web Assistant icon in the SQL Server program group. FIG. 23.1 The opening screen for the Web Assistant. When starting the Web Assistant, specify the server that contains the database and provide either a log on id, and password, or alternatively select the log on security of NT itself. In Figure 23.1 you can see that I chose the latter. Like all other Wizards, you select the next button to proceed on to the next

step. The Web assistant logs on to the server and presents you with a window that gives you a choice of three different ways to construct your HTML pages.

Interactively Creating a Query


To interactively create a query from which your HTML page will be built, follow these steps: 1. From the query screen, select "Build a Query" from a Database Hierarchy option. 2. From the database treeview at the bottom of the window, select and expand your database to get to the tables and columns you want to include. To expand a database object, click the plus sign (+) next to it. 3. From the expanded database list, select the table(s) to use in your query. This option is equivalent to a SELECT * FROM table_name statement. 4. To select individual columns, expand the table selection. All columns are selected by default. To cancel a selection, clear the column(s). 5. In the Do You Want Any Additional Criteria... box, type additional clauses for the query, such as WHERE or ORDER BY. 6. To continue, choose the Next button. To exit, choose the Cancel button. While this method works and is real easy to use for those who are novices with Transact-SQL, I found it to be an awkward and limiting interface for those who are competent in writing their own SQL queries. The Build a Query From a Database Hierarchy window is shown in Figure 23.2. FIG. 23.2 Using the Web Assistant's Build A Query From a Database Hierarchy option.

Entering a Query as Freeform Text Option


With this option, there are no training wheels, you have to create your query as you see fit and make sure that it will act as you desire. Of course, with this option you can create a rowset that can be as complicated as your needs require, without restraints. In the example I am going to use here, I developed and tested the queries in ISQL/w, a utility program that comes with SQL-Server (see fig. 23.3). FIG. 23.3 Using ISQL/w to create queries.

Looking at the Query window in Figure 23.3, you can see that I have two Select type queries in the window. The Web Assistant treats these as two table sets in the resulting HTML page. All I need to do is cut and paste the perfected query into the Web Assistant's Freeform Query text window, as shown in Figure 23.4. Listing 23.2 shows the query that I developed for this chapter. Listing 23.2 Muti Select Query that Results in Two Rowsets Being Returned SELECT * FROM Publishers SELECT publishers.pub_name,titles.title,titles.type, titles.price, authors.au_fname, authors.au_lname FROM publishers Left Join titles ON publishers.pub_id = titles. Pub_id LEFT JOIN titleauthor ON titles.title_id = titleauthor.title_id LEFT JOIN authors ON titleauthor.au_id = authors.au_id ORDER BY publishers.pub_id FIG. 23.4 The perfected Transact-Sql Query pasted from ISQL/w into the Web Assistant.

Scheduling a Web Page Task


With the query now pasted into the Web Assistant, I move on to the next window, which includes a single drop down box titled Scheduling Options. There are five choices that determine the life span of your Web page task they are described in the following list:
q

NOW Creates the HTML page immediately and deletes the task from the database when finished. This is a one-time task. LATER Creates the HTML page at a later date & time that you specify in an argument window. This is also a one time task that is deleted immediately after it runs on the day and time specified. WHEN DATA CHANGES Creates triggers based on your selection of tables, and/or columns to monitor. This task remains until removed and repeats every time that one of the triggers is called. ON CERTAIN DAY OF THE WEEK The task executes on the specified days of the week until the task is dropped. ON A REGULAR BASIS The task repeats on a regular schedule of n minutes, hours, days, or weeks. The task repeats until dropped from the task list.

This is a very flexible system for scheduling Web page updates. You can schedule one time tasks, triggered tasks, or regular timed schedules. Figure 23.5 shows the Web Assistant indow in the When Data changes Mode. The format of this window changes depending on your selection of a scheduling option.

FIG. 23.5 Setting a scheduling option in the Web Assistant.

Using File Options with the Web Assistant


The next Web Assistant page, after scheduling, is the Files Options page. Of course the first option is the final location path of the HTML page to be generated. You need to provide a fully qualified path, or a UNC path for the page to which you are writing. In the next option, you decide if you want to use a template file. I will go into more detail on this option in the "Building a VBScript Based Web Page" later in this chapter. For now I'll leave it unchecked and the Web Assistant will progress on to some basic page customizations. On the File Options page, there is also an option for including one URL link, or several links from a table in the database. Using this option, places one or more URL links at the bottom of the resulting Web page. You can view the File Options page in Figure 23.6. FIG. 23.6 Filling in the File Options of the Web Assistant.

Formatting the Page with the Web Assistant


Don't get exited; there are not a lot of options here. You can select a header type for the page title from a drop down list that includes H1 to H6. You can also select fixed or proportional font, bold and/ or italic text for the output data. You can also add a Date-time stamp to the top of the page and allow column names for the data tables. Figure 23.7 shows the resulting HTML page from the supplied query. FIG. 23.7 The HTML page made by the Web Assistant shown in Explorer 3.0b1.

Building a VBScript-Based Web Page


If the Web page shown in Figure 23.7 knocked your socks off and met with your ideas of what a Web page should look like, move on to the next chapter because you are done here. Still reading? Okay, let's build a real Web page using the Web Assistant. There are only two things you have to do: write a template file, and specify that file in the File Options page. In this example, I want to have a ComboBox loaded with publisher names. When I select a publisher from the ComboBox, I want a book printed by that publisher to appear in the text boxes below. The first thing we have to do is create the query that drives the page. That query is in Listing 23.2 shown earlier in the chapter. The next step is to create a template that the Web Assistant will use to make this page. The first part of the template's code populates the template with the ActixeX controls that will contain

the data and lay out the visible part of the HTML page. This part is contained in Listing 24.3.

Listing 23.1QUEWEB2.TPL The Layout Portion of the Template File Including the ActiveX Control Declarations <HTML> <HEAD> <TITLE>SQL Server Web Assistant Demo 2</TITLE> </HEAD> <BODY> <OBJECT ID="ieList" WIDTH=1 HEIGHT=1 CLASSID="CLSID:8BD21D20-EC42-11CE-9E0D-00AA006002F3"> <PARAM NAME="ScrollBars" VALUE="3"> <PARAM NAME="DisplayStyle" VALUE="2"> <PARAM NAME="Size" VALUE="5151;811"> <PARAM NAME="MatchEntry" VALUE="0"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <OBJECT ID="ieCombo" WIDTH=391 HEIGHT=24 CLASSID="CLSID:8BD21D30-EC42-11CE-9E0D-00AA006002F3"> <PARAM NAME="VariousPropertyBits" VALUE="746604571"> <PARAM NAME="DisplayStyle" VALUE="3"> <PARAM NAME="Size" VALUE="10336;635"> <PARAM NAME="MatchEntry" VALUE="1"> <PARAM NAME="ShowDropButtonWhen" VALUE="2"> <PARAM NAME="FontHeight" VALUE="200"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <br> <br> TITLE: <BR> <INPUT TYPE=TEXT NAME="txtTitle" Size=100> <BR> TYPE: <BR> <INPUT TYPE=TEXT NAME="txtType" Size=100> <BR>

PRICE: <BR> <INPUT TYPE=TEXT NAME="txtPrice" Size = 100> <BR> AUTHOR: <BR> <INPUT TYPE=TEXT NAME="txtName" Size = 100> The ComboBox and ListBox need to be populated with the rowsets returned from the query. I should note here that a ListBox is being used to receive data in place of a data array. At the time of writing this book, arrays were not yet working in VBScript. By the time you read this, they should be working, which will make some of the contortions being performed here unnecessary. Anyway, what I do is load all of the query results into these two controls separating the fields with a semicolon. Use the <%insert_data_here%> place holder to mark where the data fields should be placed. The fields will be filled in the order that the query requests them in the Select part of the query. Take a look at that code now in Listing 23.4.

Listing 23.4QUEWEB2.TPL The Code that Inserts the Query's Data into the ActiveX Controls <SCRIPT LANGUAGE="VBSCRIPT"> Dim Pubname Dim AllData <%begindetail%> PubName = "<%insert_data_here%>" & ";" & "<%insert_data_here%>" ieCombo.additem PubName <%enddetail%> <%begindetail%> ielist.additem "<%insert_data_here%>" & ";" & "<% insert_data_here%>" _ & ";" & "<%insert_data_here%>" & ";" & "<%insert_data_here%>" _ & ";" & "<%insert_data_here%>" & ";" & "<%insert_data_here%>" <%enddetail%> The <%begindetail%><%enddetail%> pair mark off the boundaries of a given rowset. That means that the procedure will iterate through all of the rows returned and place the data in that rowset repeatedly, along with what ever other code is between those markers, in the resulting file. To understand what I mean, look at the corresponding section in the resulting HTML page in Listing 23.5.

Listing 23.5QUEWEB2.HTML The Resulting Section of Code Returned by the sp_makeweb Procedure <SCRIPT LANGUAGE="VBSCRIPT"> ieCombo.additem "0736" & ";" ieCombo.additem "0877" & ";" ieCombo.additem "1389" & ";" ieCombo.additem "1622" & ";" ieCombo.additem "1756" & ";" ieCombo.additem "9901" & ";" ieCombo.additem "9952" & ";" ieCombo.additem "9999" & ";" ... ...

& & & & & & & &

"New Moon Books" "Binnet & Hardley" "Algodata Infosystems" "Five Lakes Publishing" "Ramona Publishers" "GGG&G" "Scootney Books" "Lucerne Publishing"

What you see in Listing 24.5 is the results of the first <%begindetail%><%enddetail%> pair. Finally to complete our template file, add the VBScript code that parses the data into its component parts and loads those parts into the TextBoxes. There is also a click event of the ieCombo that calls the parsing procedure. It's all in Listing 24.6. Listing 23.6QUEWEB2.TPL The click Event and Parsing Procedures Sub ieCombo_Onclick SeparateData End sub Sub SeparateData Dim lngStart Dim lngEnd Dim strItems Dim strName strItems = ielist.list(ieCombo.ListIndex) lngStart = 1 lngEnd = instr(lngStart,strItems,";") txtTitle.Value = mid(strItems,lngStart,lngEnd-lngStart) lngStart=lngEnd + 1 lngEnd = instr(lngStart,strItems,";") txtType.Value = mid(strItems,lngStart,lngEnd-lngStart) lngStart=lngEnd + 1 lngEnd = instr(lngStart,strItems,";") txtPrice.Value = mid(strItems,lngStart,lngEnd-lngStart) lngStart=lngEnd + 1 lngEnd = instr(lngStart,strItems,";") strName = mid(strItems,lngStart,lngEnd-lngStart) lngStart=lngEnd + 1 lngEnd = instr(lngStart,strItems,";")

strName = strName & " " & mid(strItems,lngStart,lngEndlngStart) lngStart=lngEnd + 1 txtName = strName End Sub </SCRIPT> </BODY> </HTML> After this template file is stored include the template file in the Web Assistant's Option page by specifying the fully qualified path to it. After completing the remaining steps of the Web Assistant's process, the page will be created by SQL Server. That page will look like the one in Figure 23.8. FIG. 23.8 The queweb2.html page displayed in Explorer 3.0b1. The above example shows how the Web Assistant can help you to create your Web pages. As another example, using only the sp_makewebtask procedure, I'll show how you can construct procedures that will do the same thing without the Web Assistant. First I'll make a slightly prettier template file that uses a table to contain the detail TextBoxes. The code in Listing 23.7 shows that template file.

Listing 23.7SQL6WEB.TPL A Template File Using a Table and Text Box Combination to Display Data <HTML> <HEAD> <TITLE>SQL Server Multiple Queries with Template Web Sample</ TITLE> <BODY> <H1>Books For Sale</H1> <HR> <OBJECT ID="ieList" WIDTH=1 HEIGHT=1 CLASSID="CLSID:8BD21D20-EC42-11CE-9E0D-00AA006002F3"> <PARAM NAME="ScrollBars" VALUE="3"> <PARAM NAME="DisplayStyle" VALUE="2"> <PARAM NAME="Size" VALUE="5151;811"> <PARAM NAME="MatchEntry" VALUE="0"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT>

<OBJECT ID="ieCombo" WIDTH=391 HEIGHT=24 CLASSID="CLSID:8BD21D30-EC42-11CE-9E0D-00AA006002F3"> <PARAM NAME="VariousPropertyBits" VALUE="746604571"> <PARAM NAME="DisplayStyle" VALUE="3"> <PARAM NAME="Size" VALUE="10336;635"> <PARAM NAME="MatchEntry" VALUE="1"> <PARAM NAME="ShowDropButtonWhen" VALUE="2"> <PARAM NAME="FontHeight" VALUE="200"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> <br> <br> <TABLE BORDER=5> <TR BGCOLOR="YELLOW"> <TH Size = 35>Table Name</TH> <TH Size = 35>Table Data</TH> </TR> <TR> <TD BGCOLOR="TAN">AUTHOR ORDER</TD> <TD> <Input Type=Text Size=30 ID="AUTHORD" VALUE="TEST"> </TD></TR> <TR> <TD BGCOLOR="TAN">AUTHOR NAME</TD> <TD> <Input Type=Text Size=30 ID="AuthName" VALUE="TEST"> </TD></TR> <TR> <TD BGCOLOR="TAN">PRICE OF BOOK</TD> <TD> <Input Type=Text Size=30 ID="AUTHPrice" VALUE="TEST"> </TD></TR> <TR> <TD BGCOLOR="TAN">GROSS SALES</TD> <TD> <Input Type=Text Size=30 ID="AUTHSales" VALUE="TEST"> </TD></TR> <TR> <TD BGCOLOR="TAN">PUBLISHER ID</TD> <TD> <Input Type=Text Size=30 ID="AUTHPubID" VALUE="TEST"> </TD></TR> </TABLE> <P>

<Script Language="VBScript"> blnLoading = True <%begindetail%> ieCombo.additem "<%insert_data_here%>" ieList.addItem "<%insert_data_here%>" _ & ";" & "<%insert_data_here%>" _ & " " & "<%insert_data_here%>" _ & ";" & "<%insert_data_here%>" _ & ";" & "<%insert_data_here%>" _ & ";" & "<%insert_data_here%>" <%enddetail%> blnLoading = False Sub ieCombo_Click() dim lngItem If blnLoading then Exit Sub SeparateData End Sub Sub SeparateData Dim lngStart Dim lngEnd Dim strItems strItems = ielist.list(ieCombo.ListIndex) lngStart = 1 lngEnd = instr(lngStart,strItems,";") AuthOrd.Value=mid(strItems,lngStart,lngEnd-lngStart) lngStart=lngEnd + 1 lngEnd = instr(lngStart,strItems,";") AuthName.Value=mid(strItems,lngStart,lngEnd-lngStart) lngStart=lngEnd + 1 lngEnd = instr(lngStart,strItems,";") AuthPrice.Value=mid(strItems,lngStart,lngEnd-lngStart) lngStart=lngEnd + 1 lngEnd = instr(lngStart,strItems,";") AuthSales.Value=mid(strItems,lngStart,lngEnd-lngStart) lngStart=lngEnd + 1 End Sub </Script> <P> <A HREF = "http://www.w3.org.pub/WWW/">The World Wide Web Consortium</A><P> <A HREF = "http://www.w3.org/hypertext/WWW/MarkUp/html3/ contents.html">HTML 3 specs</A><P> <A HREF = "http://www.microsoft.com">MICROSOFT</A><P> </BODY> </HTML>

To use this template in conjunction with the sp_makewebtask stored procedure we'll call up the ISQL/ w file. And enter the text shown in Listing 23.10. The ISQL/w query screen looks like Figure 24.9. FIG. 23.9 Using the ISQL/w program to execute the sp_makewebtask procedure.

Listing 24.2WEBTEST4.SQL A Typical sp_makewebtask Procedure USE pubs go EXECUTE sp_makewebtask @outputfile = 'D:\QUE\CHAPT24\SQL6WEB. HTM', @query = 'SELECT title, au_ord, au_fname, au_lname, price, ytd_sales, pub_id FROM authors, titles, titleauthor WHERE authors.au_id = titleauthor.au_id AND titles.title_id = titleauthor.title_id', @templatefile = 'D:\QUE\CHAPT24\SQL6WEB.TPL', @dbname = 'PUBS', @rowcnt = 25, @whentype = 1 go Just by executing this query the web page shown in Figure 23.10 will be created. FIG. 23.10 The Web page created by the query in Listing 23.8.

From Here...
The Web extensions for SQL Server provide a very attractive alternative to the more complex IDC method of providing data. The stress on the server is also minimized since the pages are not created during user demand time. The Web server merely sends the already existing pages out. The examples shown here are really simple and do not touch on too deeply on more complex strategies that the Web Extensions could be targeted towards. What was presented here was really intended to show you how you could use VBScript to enhance the Web pagers produced through the use of customized template files.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

CHAPTER 24 - Building Internet Rating Applications


by William R. Beem

As mainstream consumers converge upon the Internet, they bring with them a collection of baggage accumulated over the past few decades. The Internet was once the playground of academics and government agencies. For the most part, your average person off the street would have considered the content listless and dull. The content today is quite a bit more diverse. As consumers move into the Internet, they bring along the things that interest them most. While Madison Avenue types try to sell us everything from Pepsi to the latest movie, other parts of the Internet aren't quite as wholesome. One of the most pervasive items in the consumer world is sex. For good or bad, it's on the Internet and the Web. How did the Internet move from boring technical diatribes to sex-for-sale? It's not that hard to imagine. Back in the 1980s, parents wanted to provide their college-bound youth with computers. The universities complied with the idea by providing network connections to each dorm room, and sometimes requiring a personal computer for admission. The next part is a simple matter of human nature. What happens when you provide a bunch of college educated people with raging youthful hormones access to an enormous network? You get creative ways to distribute sex-related material around the world in the blink of an eye. As you can see, the influence of sex permeated the Internet before the average consumer jumped on board in the 1990s. In fact, sex-related topics probably helped drive Internet acceptance, just as sexy movies spurred VCR sales in the 1980s. While some of the prudish among us may wish to eradicate sexual content completely, that simply isn't going to happen. There's too much interest among some users and that means someone will always be around to provide material for them to use. There are still problems remaining, though. Chief among them are the following:
q q q q q

Evaulating the content The material is clearly inappropriate for children. Evaluating the appropriateness of use Corporate users accessing these sites on company time waste productivity. Evaluating the usefulness of the information

Some people simply don't want this material in their life.

Content Issues
The chief concern right now is how easily it is for anyone to access sexually related Internet sites, whether intentionally or not. In other areas of life, we have safeguards to prevent children from accessing adult entertainment clubs, movies, and magazines. With a broader range of people using the Internet, it seems appropriate that we devise similar safeguards for online access to similar adult material. Although many people never consider corporate users wasting time at work, the problem is very real. Some corporate studies estimate that employees waste as much as 40 percent of their time on the Web viewing sites unrelated to their work. Interestingly, not all of them are looking for sexual content. One major aerospace firm has a tremendous problem with employees spending more time looking at current sports scores than reviewing the less exciting technical publications on the Web.

It's Not Censorship


Not everyone is trying to prevent someone else from accessing inappropriate material. Some people just want to protect themselves from unwanted images. It's quite easy to run across sexual content while surfing from one link to another, or by performing searches on seemingly harmless topics. For example, not everyone who enjoys photography wants to follow links to some of the adult subjects often associated with the profession. A person interested in building models may find unanticipated results in the results from a search query. While investigating the topic for this chapter, I discovered far more adult links than links to Internet Ratings material. Each of these scenarios provides incentive for some measure of content selection. Although the government recently passed an intrusive Communications Decency Act (CDA), the reality is that many of these sites are still online and do nothing to prevent access by those who shouldn't be there. Fortunately, the Internet is a community unto itself, and it responds when a need arises. A free market economy tends to rise up and meet demand. In this case, we have several new software packages on the market that enable parents and supervisors to control which Internet sites their children and users may access. Some of these packages include SurfWatch and CyberPatrol. Online services, such as CompuServe and America Online, are also providing parental controls features with their user software.

The Platform for Internet Content Selection (PICS) Standard


In August of 1995 representatives from 23 organizations gathered with MIT's World Wide Web Consortium to discuss content labeling for use with content selection software. The attendees had the following two major considerations in mind:
q

Allowing parents, schools, and employers to control what computer users under their care can

or cannot access Providing a positive, self-regulating method as an alternative to government intervention

The result of the conference was PICS, the Platform for Internet Content Selection. PICS design allows a supervisor to block access to certain Internet sites. The key difference between PICS and the CDA is censorship. While the government bill seeks to eradicate anything it considers inappropriate, the PICS standard allows the user to merely avoid that which it doesn't want to see without imposing the same restrictions on other Internet users. The PICS standard facilitates the following:
q

Self-rating: It enables content providers to voluntarily label the content they create and distribute. Third-party rating: It enables multiple, independent labeling services to associate additional labels with content created and distributed by others. Services can devise their own labeling systems, and the same content can receive different labels from different services. This does not require the cooperation of the content provider. Ease of use: It allows supervisors to use ratings and labels from diverse sources to control information presented to users under their control.

A supervisor is someone responsible for setting the blocking criteria for Internet users. A supervisor can be a parent, teacher, employer, or anyone else who takes responsibility for the user's Internet access.

It Takes Two
PICS requires action on both the client and server side of the connection. Content providers apply labels in their HTML code that describe the rating level of the material on their site. The users require software that detects these labels and acts upon them based upon permission settings that a parent or supervisor defines for the user. If both parties adhere to the same rating system, a user does not need to actually see the material in order to know that he or she wants to block it from view. How do we define that which is or isn't appropriate? There are three factors at work here, as follow:
q

q q

The supervisor's style or choice of content: Some people, particularly parents and employers, are responsible for the actions of others. The recipient: The same rules may not apply to all users across the board. The context: Something completely appropriate at home may have no place at school or work.

These three factors present a need for a flexible method of blocking content. They also present a problem, since different people disagree upon which content is or isn't harmful. Consider television

programming as an example. In accordance with FCC regulations, broadcast television stations restrict nudity and sexual content in programs. Nevertheless, television is rife with blood and guts violence. Suggestively sexual programming comes on late in the evening, presumably when parents are home to supervise their children's watching habits, yet Saturday afternoons are often filled with war movies. There's a growing movement objecting to television violence. The PICS standard tackles this problem by defining a mechanism for implementing rating structures, and then allowing others to implement the ratings system. Prior to PICS, a cottage industry came forth to fill the need. Instead of determining the ratings structure themselves, supervisors subscribed to services that catered to their needs. Different entities defined these subscription-based rating services, such as selection software business entities CyberPatrol and SurfWatch.

The Old Way


The selection software positions itself between the user and the online services, and uses a predetermined list of URLs known as unacceptable, or at least questionable, sites (see fig. 24.1). The software also uses a list of labels and keywords to determine if an unknown site is acceptable given the supervisor's criteria. Unfortunately, none of these products could process labels provided by competitors. This left content providers with a dilemma: how to provide adequate warning for selection software without spending an inordinate amount of time complying with an ever increasing number of conflicting products. There was a clear and present need for a content selection standard. FIG. 24.1 Content selection software before PICS could block some pre-defined sites but not others.

The PICS Way


PICS separates the software from the labels. Any PICS-compatible selection software product can read PICS compliant labels implemented on a server. This means the content providers can implement one set of labels, and users can choose the selection software they desire (see fig. 24.2). FIG. 24.2 PICS-compliant selection software uses labels provided by publishers and ratings services, as well as the supervisors criteria, to provide more accurate content blocking. The PICS standard does not provide selection software or a specific rating system. It merely establishes the conventions for describing rating systems and label formats. The open nature of the PICS standard allows different rating systems for use by the same PICS-compliant software product. These ratings aren't restricted to adult-oriented material. As previously mentioned, the aerospace employer whose employees are addicted to sports scores may seek to block ESPN's Web site. A corporate intranet may use labels as a measure of security to access confidential materials published on the internal network.

The key element that allows selection software to read any set of labels is a new MIME type (application/pics-service) that specifies a standard format for describing a labeling service. The selection software reads service descriptions in this format to determine content labels. Supervisors use this information to configure their selection software. Listing 24.1 demonstrates a sample rating service based upon the MPAA movie rating scale. Listing 24.1 Setting Up a Rating Service ((PICS-version 1.0) (rating-system "http://moviescale.org/Ratings/Description/") (rating-service "http://moveiscale.org/v1.0") (icon "icons/moviescale.gif") (name "The Movies Rating Service") (description "A rating service based upon the MPAA's movie rating scale") (category (transmit-as "r") (name "Rating") (label (name "G") (value 0) (icon "icons/G.gif") (label (name "PG") (value 1) (icon "icons/PG.gif") (label (name "PG-13") (value 2) (icon "icons/PG-13.gif") (label (name "R") (value 3) (icon "icons/R.gif") (label (name "NC-17") (value 4) (icon "icons/NC-17.gif")))) The initial section points to a URL that describes the labeling system and criteria for assigning ratings, an icon, a name, and a longer description of the service. Referring to resources by their URLs makes it possible to match a label with its associated resource, even if distributed separately. This separation is important, since it allows a ratings service to define labels for sites that may not wish to cooperate with the service. Anything named by a URL can have a label attached to it, including resources accessed by FTP, Gopher, HTTP, or Usenet. The PICS standard also defined a URL naming system for IRC so that supervisors can also restrict access to unacceptable chat rooms. The latter section of Listing 24.1 describes the categories and its dimensions. In this case, there is only one category. Another example may have categories based upon Sex, Violence, and Language, each with its own series of levels. A supervisor creating a definition for a user, or group of users, must choose the level at which the selection software blocks content. If a user has a PG level clearance, the software denies access to a PG-13 (value 2) and higher content page. The following are two optional security features that labels can include:
q q

Message integrity check Digital signatures

The message integrity check, in the form of an MD5 message digest, enables the software to detect whether or not something changed the resource after creating the label. A digital signature on the

contents of the label itself allows the selection software to guarantee that a label was really created by the service it references. Think of this as a seal of approval. If you subscribe to a service that provides ratings, it can create a unique, unforgeable digital signature to associate with its labels. If a label claims to represent this service provider, a quick check of its signature verifies whether it's authentic or not.

Rate that URL


As previously mentioned, PICS provides an open platform for multiple, independent rating services. A rating service is an individual, group, or organization that provides content labels for information provided on the Internet. The new MIME type, application/pics-service, is the base type for defining a label. Each label has a rating system that defines it. A rating system specifies the dimensions used for labeling, the scale of allowable values on each dimension, and a description of the criteria used to assign values. The Movie Scale used in Listing 24.1 is a single dimension rating system with five allowable values, G through NC-17. Other rating systems may have multiple dimensions. Each rating system is identified by a valid URL. By doing so, several services can use the same rating system and refer to it by its unique identifier (the URL). Using a URL to name a rating system allows users to access it and obtain a human readable description of the rating system. Although the format for this description is unspecified, it should provide a supervisor with enough information about the rating system to allow for an accurate decision on whether the system fits the supervisor's needs or not. A content label, or rating, has the following three parts that contain information about a document:
q q

The URL naming the rating service that produced the label A set of PICS-defined attribute value pairs, which provide information about the rating (date the rating was assigned, date it expires, and so on) A set of rating system defined attribute pairs, which actually rates the item along various dimensions or categories

Describing the application/pics-service Type Listing 24.1 shows the general format of a MIME application/pics-label type. Unfortunately, it's not a complete example. As mentioned previously, a rating system can have more than one category. Likewise, these categories can have different options than the ones displayed in the sample. This section displays a few more examples in HTML code Web page designers who wish to provide their own PICS ratings transmissions implement these HTML tags in their Web page design. Clients using PICS-compliant software will translate these tags and allow or deny access to the site based upon how the client's rules and preferences interpret the information presented by these tags. (category

(transmit-as "Value") (name "Value Index") (min 0.0) (max 1.0)) This category tag still defines a transmission name and a longer name value. Notice there are some differences, though. Notably, this category does not provide any labels. Instead, it defines this category with a rating range of 0.0 to 1.0. A rating service can choose a value in between for the content, and supervisors can also choose a value inside the range to block content. (category (transmit-as "Subject") (name "Document subject") (multivalue true) (unordered true) (label (name "Sex") (value 0)) (label (name "Violence") (value 1) (label (name "Language") (value 2)) (label-only)) The preceding category sample demonstrates a rating system for a document that contains multiple subjects. A supervisor may choose to deny access based upon any one of these labels, or perhaps a combination of labels. (category (transmit-as "Color") (name "Picture color") (integer) (category

(transmit-as "Hue") (label (name "Blue") (value 0)) (label (name "Red") (value 1)) (label (name "Green") (value 2))) (category (transmist-as "Intensity") (min 0) (max 255)))) This sample demonstrates that a category can also have sub-categories that make up its properties. Note the flexibility that this combination allows. The Hue category provides three attributes, multiplied by an Intensity category range of 256 values. Some Semantic Issues There are always rules for any kind of code, and the syntax of application/pics-service attributes are no exception. This section describes some of the syntax rules you must observe when creating your application/pics-service attributes.
q

application/pics-service attributes ignore white space, except in quoted strings. Multiple white space characters are treated as a single white space character. Transmitted names and quoted strings are case sensitive. Option names and other tokens are case insensitive. The extension attribute allows PICS to add more attributes at a later time. Each extension requires a quoted URL to avoid duplication of extension names. The URL provides a humanreadable description of the extension. Extensions can be optional or mandatory. Selection software can disregard optional extensions if it doesn't understand how to implement them. Selection software should reject any mandatory extensions that it doesn't understand. The PICS specification requires US-ASCII so that it can transmit over Internet lines to computers on multiple platforms. Any options defined in a particular service-info construct applies to all labels within that construct, unless an option in a specific label overrides it. Numbers in PICS labels can be integers or fractions with no greater range or precision than that provided by IEEE single-precision floating point numbers. You must use the multi-value syntax when the value of a particular scale has either zero or more than one value. Additionally, you can use it for a single or multi-value field when there

is exactly one value. The only options that can occur more than once in a particular single-label or service-info are comment and extension. For each instance of the extension option, you must provide a unique quoted URL to define the extension.

Labels and Label Lists


The PICS specification uses a labellist to transmit a set of PICS labels. The format is the same application/pics-labels MIME type discussed previously. The format transmits labels, as well as reasons why a label may be unavailable, along with a document. The labellist is always surrounded by parentheses and begins with the PICS version number. The following fragment displays a sample label list: labellist :: '(' version service-info+ ')' Label lists either specifies that there are no labels available or it is separated into sections of labels for each rating service. The URL of each service is specified as the serviceID. Following the URL is either an error message indicating why no labels are available from that service, or an overall set of optional information followed by the keyword labels and the labels from the service. The optional information applies to every label from the service, unless an a specific label has its own option to override the general service option.

Embedding Labels in HTML


You can imbed PICS labels in HTML files as meta-information using the HTML META element. Use the HTTP header equivalence, as in the following example: <META http-equiv="PICS-Label" content='labellist'>

Note that the content attribute uses single quotation marks, since the PICS label syntax uses double-quotation marks.

PICS includes an extension to HTML that allows a client to request one or more labels be included in a header along with a document. HTTP servers should only include PICS label headers if requested by the client, and then only include labels from services requested by the client. Including unrequested labels adds unnecessary burden on the bandwidth and serves no purpose, since the client ignores those labels.

The PICS extension to HTML only works with HTTP protocol. It's possible that later revisions of the PICS standard will incorporate extensions for other protocols.

An example PICS client request appears as follows: GET some.html HTTP/1.0 Protocol-Reqest: (PICS-1.0 {params full {services "http://www.someplace.org/v1.0"}}} Here's what has happened so far. First, the client sends a request for some.htmla document on a Web server. The client's request asks for the full label of the document from the rating service at http://www.someplace.org. A client interested in examining a rating before retrieving the full document can substitute the word HEAD instead of GET in the request. The server responds with the header shown in the following listing, but not the document itself. This provides the user an opportunity to check ahead to see if the document has a suitable rating before spending the time to retrieve the document. The server's response to the client appears as follows: HTTP/1.0 200 OK Date: Tuesday, 07-May-96 13:35:34 GMT MIME-version: 1.0 Last-modified: Thursday, 07-May-96 05:12:47 GMT Protocol: {PICS-1.0 {headers PICS-Label}} PICS-Label: (PICS-1.0 "http://www.someplace.org/v1.0" labels on "1994.11.05T08:15-0500" exp "1995.12.31T23:50-0000"

for "http:/www.website.com/some.html" by "William Beem" ratings (value 0.7 intensity 0 color/hue 1)) Content-type: text/html ...contents of some.html... The server responds by sending back the label in a PICS-Label header, and also the requested document. The format of the PICS-Label headers field (labellist) allows the server to reply with either a label or an explanation of why the label isn't available. It's inappropriate for a server to generate an HTTP error status if the document is available, but the labels are unavailable. Selection software can also request PICS labels separately from the documents to which they refer. In order to do this, a client contacts a label bureau. Label bureaus are HTTP servers that understand a particular type of query syntax. It provides labels for documents on other servers and for documents available through other protocols than HTTP. These label bureaus are most likely run by rating services, and may charge a fee for label queries. In fact, the PICS standards documentation encourages rating services to act as label bureaus. Suppose a ratings service has a URL on the Web called http://www.ratem.org/Ratings. It decides to run a label bureau to dispense labels for its own documents. The following sample requests the URL to send a single label that applies to everything in the /images directory of another URL titled http:// www.nasty.net. GET /Ratings?opt=generic& u="http%3A%2F%2www.nasty.net%2Fimages"& s="http%3A%2F%2Fwww.ratem.org"& HTTP/1.0

Notice the use of %3 to represent a colon (:) and %2 to represent a forward slash (/). This is necessary for encoding characters within a URL. RFC-1738 has more complete details on this topic.

Upon receiving this query, the server sends back a MIME application/pics-label type document. The document should be complete, containing all options contained within the label. From this information, the client can decide whether to proceed into the /images directory or not.

Digital Signatures
As discussed in Chapter 8, "Security," digital signatures provide a mechanism to determine whether the contents of a data file or document were altered. The PICS standard makes use of this technology to determine whether a document changed since it was last labeled. This is quite a frequent occurrence since Web pages tend to change on a regular basis. It's possible that a change can happen due to some unauthorized access, but PICS labels have three option fields intended to identify and deter such events. These fields are as follows:
q

At: Assuming that the Web page owner accurately identifies the last modification time, this field detects updates to the document made after the label was created. Until or exp: This is an expiration date for the document. The label becomes invalid if something changes the contents prior to this date. MD5: Message Digest 5 is a well-known checksum algorithm used in many encryption methods. It creates a message digest based upon the contents of the document. When a user retrieves the document, an algorithm compares its contents to the message digest using the same algorithm. It is very unlikely that the results will be the same if something changed the document. This technique is perhaps the best of the three, since it prevents even knowledgeable criminals from making undetected document changes. Since it's possible to embed PICS labels inside the document, take care to ensure that the message digest computation does not include the PICS label itself. It's best to compute the message digest after removing all META elements and white space in HTML documents.

The next problem is to ensure that the labels received from a rating service are indeed coming from that service, and that they haven't been altered during transmission. PICS uses digital signatures to address both problems. The rating service signs its labels with a public key pair. The service keeps its private key secret and distributes the public key to anyone who wishes to use the service. Upon creating the label, the service computes a message digest of the label using the MD5 algorithm and then encrypts it with the service's private key. The result of this process is the digital signature. The signature gets converted to US-ASCII using a base64 encoding technique and is then stored in the signature-rsa-md5 option of the label it transmits to the client. After receiving the label, the client can verify the signature by converting the label back to binary form and re-computing the message digest. The client must also convert the contents of the signaturersa-md5 option back to binary and decrypt it using the service's public key. Finally, a comparison of the new message digest and the decrypted message digest should provide an exact match if the document is authentic. While this sounds like a lot of work for the user, that's not really the case. It's a lot of work for the programmer, since that is who should automate all of these steps when a user receives a label.

PICS specifically requires the use of RSA signature algorithm with the MD5 message digest. This may change in the future. Such a change only requires a new label option that supports a different algorithm pair. PICS does not specify the key length necessary for encryption. This detail is left to the users and rating services to decide.

SafeSurfA Ratings Example


SafeSurf is a company that provides content selection software and a rating service targeted at parents who want to protect their children from inappropriate content on the Internet. Parents using the SafeSurf Rating Standard can activate several layers of blocking based upon what the parents approve. Something parents find unsuitable for a small child may perhaps be less restricted for a teenager. SafeSurf maintains a master database of categories and updates new categories in as timely a manner possible. This section illustrates a rating scheme using SafeSurf's published categories and their associated levels. Table 24.1 is a guide that relates to the numbered items presented in the lists that follow. Parents can choose any level they want, regardless of title. Table 24.1 SafeSurf Ratings Scheme Adult Themes with Caution Levels Caution Level Description 0 1 2 3 4 5 6 7 8 9 Age Range All Ages Older Children Teens Older Teens Adult Supervision Recommended Adults Limited to Adults Adults Only Explicitly for Adults Profanity Rating Number Rating Name 1 2 Subtle Innuendo Explicit Innuendo Description Subtly implied through the use of slang Explicitly implied through the use of slang

3 4 5 6 7 8 9

Technical Reference Dictionary, encyclopedia, news, technical references Non-Graphic-Artistic Limited non-sexual expletives used in an artistic fashion Graphic-Artistic Graphic Detailed Graphic Explicit Vulgarity Explicit and Crude Non-sexual expletives used in an artistic fashion Limited use of expletives and obscene gestures Casual use of expletives and obscene gestures Heavy use of vulgar language and obscene gestures. Unsupervised Chat Rooms Saturated with crude sexual references and gestures. Unsupervised Chat Rooms Heterosexual Themes

1 2 3 4 5 6 7

Subtle Innuendo Explicit Innuendo

Subtly implied through the use of a metaphor Explicitly implied (not described) through the use of a metaphor

Technical Reference Dictionary, encyclopedia, news, technical references Non-GraphicArtistic Graphic-Artistic Graphic Detailed Graphic Limited metaphoric descriptions used in an artistic fashion Metaphoric descriptions used in an artistic fashion Descriptions of intimate sexual acts Descriptions of intimate details of sexual acts Explicit descriptions of intimate or Inviting details of sexual acts designed to Participation arouse. Inviting interactive sexual participation. Unsupervised Sexual Chat Rooms or Newsgroups. Profane graphic descriptions or Explicitly of intimate details of sexual Inviting Participation acts designed to arouse. Inviting interactive sexual participation. Unsupervised Sexual Chat Rooms or Newsgroups. Homosexual Themes

Explicitly Graphic

Explicit and Crude

1 2 3 4 5

Subtle Innuendo Explicit Innuendo

Subtly implied through the use of a metaphor Explicitly implied (not described) through the use of a metaphor

Technical Reference Dictionary, encyclopedia, news, technical references Non-GraphicArtistic Graphic-Artistic Limited metaphoric descriptions used in an artistic fashion Metaphoric descriptions used in an artistic fashion

6 7

Graphic Detailed Graphic

Descriptions of intimate sexual acts Descriptions of intimate details of sexual acts Explicit descriptions of intimate or Inviting details of sexual acts designed to Participation arouse. Inviting interactive sexual participation. Unsupervised Sexual Chat Rooms or Newsgroups. Profane graphic descriptions or Explicitly of intimate details of sexual Inviting acts designed to arouse. Participation Inviting interactive sexual participation. Unsupervised Sexual Chat Rooms or Newsgroups. Nudity

Explicitly Graphic

Explicit and Crude

1 Subtle Innuendo 2 Explicit Innuendo 3 Technical Reference 4 Non-Graphic Artistic 5 Graphic Artistic 6 Graphic 7 Detailed Graphic 8 Explicit Vulgarity 9 Explicit and Crude Violence 1 Subtle Innuendo 2 Explicit Innuendo 3 Technical Reference 4 Non-Graphic-Artistic 5 Graphic-Artistic 6 Graphic 7 Detailed Graphic 8 Inviting Participation in Graphic Interactive Format 9 Encouraging Personal Participation, Weapon Making Sex, Violence, and Profanity 1 Subtle Innuendo 2 Explicit Innuendo

3 Technical Reference 4 Non-Graphic-Artistic 5 Graphic-Artistic 6 Graphic 7 Detailed Graphic 8 Explicit Vulgarity 9 Explicit and Crude Intolerance 1 Subtle Innuendo 2 Explicit Innuendo 3 Technical Reference 4 Non-Graphic-Literary 5 Graphic-Literary 6 Graphic Discussions 7 Endorsing Hatred 8 Endorsing Violent or Hateful Action 9 Advocating Violent or Hateful Action Glorifying Drug Use 1 Subtle Innuendo 2 Explicit Innuendo 3 Technical Reference 4 Non-Graphic-Artistic 5 Graphic-Artistic 6 Graphic 7 Detailed Graphic 8 Simulated Interactive Participation 9 Soliciting Personal Participation Other Adult Themes 1 Subtle Innuendo 2 Explicit Innuendo 3 Technical Reference

4 Non-Graphic-Artistic 5 Graphic-Artistic 6 Graphic 7 Detailed Graphic 8 Explicit Vulgarity 9 Explicit and Crude Gambling 1 Subtle Innuendo 2 Explicit Innuendo 3 Technical Discussion 4 Non-Graphic-Artistic, Advertising 5 Graphic-Artistic, Advertising 6 Simulated Gambling 7 Real Life Gambling without Stakes 8 Encouraging Interactive Real Life Participation with Stakes 9 Providing Means with Stakes

From Here...
Content controls provide a means for parents and employers to decide what is acceptable for their users to access. The key element is that supervisors have a choice in what they allow, rather than a government body dictating standards for everyone. Content controls also provide enough flexibility that different users can have customized views of the Internet, and they also allow a child to grow and access a larger variety of content as some restrictions become unnecessary. This chapter provided an overview on a topic in its infancy. The PICS standard is a version 1.0 release, which suggests that it will undergo more changes in the coming months. To help you keep abreast of the most current information, we suggest you access the following Web sites for more information. Don't worry; they're all safe.
q q q q q q

CyberPatrol at http://www.cyberpatrol.com/ CyberAngels at http://www.safesurf.com/cyberangels/ Parental Control Page at http://www.worldvillage.com/wv/school/html/control.htm PICS Standard at http://www.w3.org/pub/WWW/PICS/ SafeSurf at http://www.safesurf.com/index.html Internet LifeGuard at http://www.safesurf.com/ss_aol.html

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

Appendix A - History of the Internet

Rather than plow into a long, boring dissertation on dates (it all started in 1969) and names (Defense Advanced Research Projects Agency started it all, and it's been know as, and comprised of, DARPANET, ARPANET, MILNET, NSFNET, and Merit at one time or another), let's take a look at what the Internet was, is, and will become. When it all began, the idea was simple: create a very fault-tolerant network of military computers. By completely decentralizing administration and control, and by providing automatic routing over multiple paths, the system would be able to withstand everything from minor localized outages all the way up to nuclear war. From that humble beginning (there were initially only a handful of large computers "on the Net"), today we have a massive network-of-networks, growing at such a phenomenal rate that providing any usage figures would be meaningless by the time you read this book. Originally, the network was used to transfer data from one large facility to others. Personal computers would not be available for a decade, and widespread usage would take even longer. The Internet was the playground of the lucky few, and the elite. Mere mortals need not apply. Those of us on "the outside" would occasionally see tantalizing glimmers of it in magazine articles, or hear words like "UseNet" and "e-mail" from friends with accounts on large university mainframes. However, getting "on the Net" was simply not possible for most of us. One of the first avenues of Net access for non-insiders was a system called "The Cleveland FreeNet," which was created by CWRU (Case Western Reserve University) using Freeport software that they developed. Within a few years, numerous "Free-Nets" appeared all over the country, providing local residents basic access to the Internet. They could use e-mail, browse Gophers, access UseNet newsgroups, local community news and events, and more. Other providers also began offering Internet access, but by and large users faced an intimidating obstacle: however nifty the concept was, it never got far from its UNIX roots. Users worked with character-based shells that ran over the UNIX operating system. This meant no graphics, no buttons to click, scrollbars to slide, boxes to check, or menus to pull down. Creating e-mail required use of a

UNIX text editor and complex commands. In short, it was not for the faint of heart. For this type of access, users dialed up with a terminal program, and whatever Internet host they dialed behaved like a sort of super-BBS system. As great as it all was, there were sufficient built-in limitations to restrict it to the few brave souls who were willing to put up with the difficulties. Two things brought us where we are today: the Winsock API and the WWW. Winsock is a protocol stack that provides a layer that creates a link between Internet applications and the Internet itself. Before the creation of Winsock, there were a few approaches to TCP/IP access on PCs, but they were difficult to use, and installation and setup was tantamount to a black art. Winsock provided a consistent platform that developers could write for, and write they did. Applications like Telnet, FTP, Finger, e-mail, IRC and talk programs, newsreaders, and so forth were quickly made available for free download at FTP sites all over the world. These programs, when run over a Winsock link, made each user's computer a station on the Internet, just like any other site. Suddenly, dial-up UNIX hosts became functionally obsolete; users could send e-mail by clicking a button and typing in a convenient Windows text box, rather than learn a crude remote UNIX editor. They could browse newsgroups while downloading files, and receive e-mail at the same time. (Winsock allows multitasking, in effect, giving each running application its own virtual modem.) About this time (the early '90s), the WWW started taking off. Applications like Mosaic created the capability to "browse the Web" and see a mix of text and graphics, all tied together with hypertext style links. This created the current wave of interest in the Internet, and the demand for access spurred numerous small companies to start provider services.

You Are Here At this point in the rapidly developing history of the Internet, the "big boys" are getting into the ISP (Internet Service Provider) game. Everyone from CompuServe to telephone companies to cable TV operators are becoming ISPs. Internet access is rapidly becoming a commodity, and nearly everyone is within a local call of a dial-up modem pool at a reasonable price.

Today, access is ubiquitous. The Internet is no longer the exclusive province of the propeller-beanie and pocket-liner crowd. The next wave will not be one of access, but of content. For all its popularity, the WWW is essentially a one-way, static medium. It's sort of like television for computers. Now, with tools like VBScript, Web pages can easily be provided active content. The personal communications systems that have been predicted for years may very well arrive on the scene as littlemore than wireless browsers of an active-content-rich WWW.

Learning the concepts presented in this book will place you in the right place at the right time to position yourself to capitalize on the next major growth stage of the Internet. It's a good time to know Visual Basic.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

APPENDIX B - HTML Reference

This appendix covers all the HTML elements (or tags) supported by the current version of Internet Explorer (3.0 beta 1). This appendix is loosely based on the HTML 3.2 Standard and the Internet Explorer 3.0 documentation available with the Internet Software Development Kit (SDK). Examples demonstrating the syntax of the HTML tags are shown at the end of each section. Several of the elements are standard HTML, while others are not and may change considerably in subsequent versions of Internet Explorer. The appendix is organized into four major sections. The first contains elements that are used with the header portion of an HTML page. The second section contains elements that are used with the body portion of an HTML page; the third section contains miscellaneous tags and a brief glossary on HTML terminology. The final section contains a full list of supported color names used by Internet Explorer. Special sections are given to client-side image maps, lists, frames, tables, forms, and objects since they contain several sub-attributes and elements.

Header Tags
The <HEAD> Tag
Purpose The <HEAD> tag is what specifies the header portion of the document. It is within the <HEAD> tags that all the information describing the document should be placed. A header should exist if you plan to give your document a title, using external style sheets, or incorporating other bits of miscellaneous information that doesn't relate to the content of the page.

The New HTML 3.2 Standard implies that the header section does not necessarily have to exist for header information, scripts, and style formats.

Syntax <HEAD>...</HEAD> Attributes None. Example <HEAD> <TITLE>This is the title of the document and appears in the [ccc] title. bar...</TITLE> </HEAD>

The <LINK> Tag


Purpose The <LINK> tag provides information about what references or what is referenced by an HTML document, in terms of information that is not usually included in the document. The <LINK> tag is treated very loosely in these cases and there can be several possible attributes for this tag. The major purpose for the LINK element in Microsoft Internet Explorer 3.0 is for style sheet purposes and possibly for Visual Basic Script. Use of the <LINK> tag with style sheets is covered in the Style Sheets section (see Chapter 2, "Review of HTML"). The <LINK> tag does not have a closing tag. Syntax <LINK> Attributes Attribute Required Purpose REL Specifies a relationship to the document, for instance the value, Made, would relate to the person who made the document.

REV TITLE HREF

Specifies a reverse relationship, something that references the document the link tag is in. This is not commonly used. Specifies a title of the item the link references or is referenced by. Specifies a URL for the referenced or referencing item. Specifies what MIME type the referencing or referenced item is. In the case of style sheets, this would be, style/css.

TYPE

Example <LINK REL="style" TYPE="text/css" HREF="http://www.styles.org/formal.css">

The <META> Tag


Purpose The <META> tag allows meta-information to exist in the document. Special information that further describes the document can be included as well. Syntax <META> Attributes Attribute HTTP-EQUIV TYPE CONTENT Required Purpose Specifies what function or task to perform on the document. Internet Explorer has only one value for this: "refresh". Specifies what the purpose of the meta information. Specifies the CONTENT of HTTP-EQUIV, or TYPE.

The value, "refresh", for the HTTP-EQUIV attribute implies that the document should be refreshed after the amount of time specified by the VALUE attribute. Additionally, the VALUE attribute can specify another URL to load after a given time in the form of: VALUE = "n URL" where, n is the number of seconds to load the document and URL is the location of the document to

load. Example <META HTTP-EQUIV="refresh" CONTENT="10 http://www.yahoo.com">

The <TITLE> Tag Purpose


The <TITLE> tag specifies the title of the document it is in. The value that is encapsulated in the title tag is displayed in the title bar of Internet Explorer.

Syntax
<TITLE>...</TITLE>

Attributes
None.

Example
<HEAD> <TITLE>This is an HTML document</TITLE> </HEAD>

Body Tags
The <A> Tag
Purpose The <A>, or anchor tag, specifies a hyperlink, which is used for accessing other documents and resources. Whatever is encapsulated by the anchor tag is either an anchor, which is accessed by other resources, or a link, which accesses other anchors and resources. Syntax <A>...</A>

Attributes Attribute Required Purpose HREF NAME TARGET Example <A HREF="http://www.rt66.com/iymalluf">Go To Malluf Consulting [ccc] Services Homepage</A> Specifies the resource to hyperlink to, this can be in the form or a URL or a filename. Identifies the anchor or hyperlink Specifies the window or frame in which the resource is loaded.

The <ADDRESS> Tag


Purpose The <ADDRESS> tag renders the text it surrounds in italics to represent an e-mail, postal, or other contact address. Syntax <ADDRESS>...</ADDRESS> Attributes None. Example <ADDRESS>123 Main Street<BR> Anytown, USA 87743-0123 </ADDRESS>

The <B> Tag


Purpose

The <B> tag renders the text it encapsulates in bold. Syntax <B>...</B> Attributes None. Example The text at the end of this line is in <B>bold</B>.

The <BIG> Tag


Purpose The <BIG> tag increases the size of the text it encapsulates. The size of this text is slightly larger than normal paragraph text. Syntax <BIG>...</BIG> Attributes None. Example We want you to notice <BIG>this text</BIG>.

The <BLOCKQUOTE> Tag


Purpose The <BLOCKQUOTE> tag is used in citing references, or other material. The text that is surrounded by the <BLOCKQUOTE> tags is indented .5 inches to the right. Syntax <BLOCKQUOTE>...</BLOCKQUOTE>

Attributes Example <BLOCKQUOTE>This sentence of words is indented - can't you see???</BLOCKQUOTE>

The <BODY> Tag


Purpose The <BODY> tag specifies the beginning and the end of the Content portion of the document, or of the document that is actually displayed. Syntax <BODY>...</BODY> Attributes Attribute BACKGROUND Required Purpose Specifies an image that is tiled across the back of the screen. Specifies a background color. This color can be in the form of one of several colors names, or a hexadecimal value in the form of #rrggbb where rr is the hexadecimal value for red on the 0-255 color palette, gg and bb are the hexadecimal value for green and blue on the 0-255 color palette, respectively. The 16 standard colors and their hexadecimal equivalentS are listed in the table at the end of the section. Refer to the last section of this appendix for a full list of supported color names. Specifies the properties of the BACKGROUND attribute. The only valid value for BGPROPERTIES now, is fixed, which indicates that the graphic specified by BACKGROUND will not be tiled but rendered as a watermark. Specifies the width of the left margin of the page (values are in pixels). Specifies the color of an unvisited link in the same manner as BGCOLOR. Specifies the color of the foreground text in the same manner as BGCOLOR. Specifies the width of the top margin of the page (values are in pixels).

BGCOLOR

BGPROPERTIES

LEFTMARGIN LINK TEXT TOPMARGIN

VLINK

Specifies the color of visited links in the same manner as BGCOLOR. Color Name Hexadecimal Equivalent "Aqua" "Black" "Blue" "Fuchsia" "Gray" "Green" "Lime" "Maroon" "Navy" "Olive" "Purple" "Red" "Silver" "Teal" "White" "Yellow" "#00FFFF" "#FFFFFF" "#0000FF" "#FF00FF" "#808080" "#008000" "#00FF00" "#800000" "#000080" "#808000" "#800080" "#FF0000" "#C0C0C0" "#808000" "#FFFFFF" "#FFFF00"

Example <BODY> <H1>This</H1> <B>This</B><BR> <P>And this are in the body</P> </BODY>

The <BR> Tag


Purpose The <BR> tag inserts line breaks in HTML. Normally, there are no line breaks in HTML; text continues to flow until it reaches the end of the browser, then a line break occurs.

Syntax <BR> Attributes Attribute Required Purpose Causes all the text following the <BR> to be aligned with the margin specified by the CLEAR attribute. For instance, if there were a left aligned image tag, and a <BR> tag following some text had the attribute: CLEAR="left", then the text would be left aligned with the left-hand margin right below the image. The "right" value does the for the right side. The "all" value causes the text following the <BR> tag to be placed past all floating images.

CLEAR

Example This line has no breaks in it This <BR> line does <BR> have brea<BR>ks.<BR> <IMG SRC="test.gif" ALIGN="left">Some text is here <BR CLEAR="left"> and some text is just below the image, on the left side.

The <CENTER> Tag


Purpose The <CENTER> tag centers any text, pictures, or other entities it surrounds. Syntax <CENTER>...</CENTER> Attributes None. Example This text is left aligned.

<CENTER>This text is centered</CENTER>

The <CITE> Tag


Purpose The <CITE> tag renders text in italics and also has the same purpose as the <BLOCKQUOTE> tag: to cite references, or other material. Syntax <CITE>...</CITE> Attributes None. Example <CITE>"He didn't do it"</CITE> the reporter said.

Client-Side Image Maps


This section covers client-side image maps and how to implement them. Currently, Microsoft Internet Explorer and Netscape Navigator support client-side image maps. The USEMAP attribute of the image tag accesses client side image maps. The USEMAP attribute indicates which map it should bind to (or in essence, which map it should use). The map contains coordinate-defined areas (polygons, circles, rectangles), which outline hotspots. When the user clicks a hotspot in the image, the coordinates are compared to the area regions specified by the map and the appropriate action specified by the HREF attribute is made. Syntax <MAP> <AREA> ... </MAP> Attributes

Attribute Required Purpose NAME Gives the map a name, which is referenced by the USEMAP attribute of the <IMG> tag.

The <AREA> Tag The <AREA> tag is used to specify the various hotspots on an image. The <AREA> tag is encapsulated inside the <MAP> tag and is the only tag allowed in the <MAP> tag. The table below lists the attributes of the <MAP> tag. Attribute Required Purpose Specifies the coordinates of a hotspot area specified by the SHAPE attribute. The coordinates are specified in (x,y) pairs until the coordinates cover an area. For example, a polygon would have the value: COORDS="x1,y1,x2, y2,..." and so on. Indicates where the user will go (in the form of a URL) if they click in a region that is specified by the corresponding COORDS attribute. Indicates that if the user clicks in a region specified by the corresponding COORD tag, then no action will occur. This attribute is required if the HREF attribute is not used. Specifies the shape of the hotspot region. The valid values are: circle, rectangle, and polygon. With a circle you must specify the center point of the circle (x,y), then the radius of the circle, in that order. (COORDS="center.x, center.y,radius") With a rectangle, you must specify the coordinates of two adjacent endpoints of the rectangle (COORDS="x1,y1,adjacent.x2,adjacent.y2"). With a polygon, you specify multiple sets of (x,y) coordinates that do not overlap (COORDS="x1,y1,x2,y2,x3,y3,...").

COORDS

HREF

NOHREF

SHAPE

The values "polygon", "circle," and "rectangle" can be shortened to "poly", "circ", and "rect", respectively, for the SHAPE attribute of the AREA tag.

Example

See Listing B.3 in the Frames section for an example.

The <CODE> Tag


Purpose The <CODE> tag renders its encapsulated text in a fixed-width font, similar to that of a code listing. Syntax <CODE>...</CODE> Attributes None. Example <H2>The code for a simple C program</H2> <CODE> #include<stdio.h> <BR> main() <BR> {<BR> printf("This is a test");<BR> }<BR></CODE> The <DFN> Tag Purpose The <DFN> tag is one of the many tags that renders text in italics. Syntax <DFN>...</DFN> Attributes

None. Example This is an example of the <DFN>&lt;DFN&gt;</DFN> tag.

The <EM> Tag


Purpose The <EM> tag, is used to emphasize a particular group of words it surrounds. The text it surrounds is in italics. The only difference between the <EM> tag and other italic rendering tags is that <EM> is used in a logical sense. Syntax <EM>...</EM> Attributes None. Example You <EM>must</EM> turn on the computer to get anything done.

The <FONT> Tag


Purpose The <FONT> tag is used for changing the size, color, and face of the text it surrounds. Syntax <FONT>...</FONT> Attributes Attribute Required Purpose

COLOR

Specifies the new color of the text. The color is specified by one of several color names (noted in the <BODY> tag section) or by a hexadecimal value, in the form of #RRGGBB (where RR, GG, and BB is a hexadecimal number from 0 to FF (255) in red, green and blue respectively. Specifies the new font for the text being encapsulated. Whether the font is shown or not, depends on whether it is available on the user's system. Some common fonts are listed in the following table. Also, you can specify multiple font names in case the user does not have the first specified font (in other words, if FACE="Times, Arial, Bahamas", the Times font will be used, if it's not available, the Arial font will be used and so on.) There is technically no limit to the number of alternate fonts one can specify. Specifies the size of the text surrounded. This can be a size relative to the base size (1 by default) or a new size (from 17). A relative size to the default size (3), or to the default size specified by <BASEFONT>, can also be used (such as, SIZE="+2" means two sizes larger than the default size or "5" and SIZE="-1" is one size smaller than the default size of "2".)

FACE

SIZE

Common Font Names


q q q q q q q q q q

Arial Courier Courier New Comic Sans Ms Dingbats Expo FrankfurtGothic Script Times New Roman Wingdings

The listed fonts only work on a user's system if they are available (if the font is installed). The listed fonts are fonts that are most likely to be on a user's Windows operating system.

Example The following text is the largest size:<BR> <FONT SIZE="7">The Largest Size</FONT><BR>

The following text is one size bigger that the current text<BR> <FONT SIZE="+1">One Size Bigger</FONT><BR> <FONT SIZE="2" COLOR="blue" FACE="Arial"> This text is one size larger than the normal text, blue and is rendered in the Arial FONT </FONT>

Forms
This section is devoted to forms and how to implement them. Forms are an important tool for Visual Basic Script and they can provide more interactive Web pages. The syntax expressed in the next section is the syntax for forms in general and all the form controls or elements are encapsulated inside the form. Form Syntax <FORM>...</FORM> Form Attributes The following are attributes that forms use to specify how and where to send its data: Attribute Purpose Specifies the URL of where the data should be submitted when the user submits the ACTION form. The URL is usually a CGI (common gateway interface) program, which processes the data. Specifies how the data should be submitted. There are two valid values for METHOD. These include: "get", and "post". The Get METHOD should be used when most of the data the user submits is not going to be permanently stored (as in a search). The Post METHOD METHOD is used when all the data the user submits is intended to be kept (as in a guestbook). Also, when the Get METHOD is used, all the data in the form is appended to the URL. When the Post METHOD is used, all the data is sent via a set of variables and arrays, called the HTTP post transaction.

When using just Visual Basic Script with forms (the form is not going to be further processed), the previous attributes are unneeded. Internet Explorer 3.0 also allows for form controls (<INPUT> and <SELECT> tags) to be used without specifying a parent form.

Form Controls There are two actual tags for specifying all the form controls. These tags are the <INPUT> tag, and the <SELECT> tag. The <INPUT> tag specifies most of the form's controls, while the <SELECT> tag is used for providing list boxes and drop-down lists.
The <INPUT> Tag

The <INPUT> tag is a single tag used for specifying various form controls including the: button, text, radio, and checkbox controls. The table in this section specifies all the attributes of the <INPUT> tag and the controls you can specify. Syntax <INPUT> Attributes Attribute ALIGN Required Purpose Specifies the alignment of the image (used with the image control). Valid values are middle, bottom, and top. Indicates whether a checkbox or a radio button is selected or checked (used with radio buttons and checkboxes). CHECKED is a valueless attribute and its presence inside the checkbox, or radio input tag indicates that the button is selected. Specifies the maximum amount of characters that can be entered into a text control. Identifies the form control. Specifies the size of the control (text box or text area). For a text box, the width in characters is given SIZE="width". For a text-area, the width and the height are specified with the characters, SIZE="width, height". Used with the image control to specify the location of the image (either by URL or filename). Specifies the type of form control. See the next table for the types of form controls available and how to implement them. Gives a default value for the form control. For buttons, this gives the button a name.

CHECKED

MAXLENGTH NAME

SIZE

SRC TYPE VALUE

TYPE (control) Value Function "button" Makes a clickable button control that has no special function (see the "submit" and "reset" values.) Indicates a square box that can be checked on and off. A group of checkboxes with related data should be given the same name. The default submitted value, if none is specified, is "on." Values are submitted only if the checkboxes are checked. Indicates a hidden input control (the control is not seen by the user and is commonly used for values that the user does not need to see). Specifies a clickable image in the form which submits the coordinates of the user's click in the form of image-name.x and image-name.y. Imagename is the name of the image assigned by the NAME attribute and the appended .x and .y values are the x and y coordinates respectively where the origin (where x and y both equal zero) is at the top left-hand corner of the image. Specifies a text box in which all the input is hidden by *'s. Specifies a radio button that remains selected when clicked. If several radio buttons are given the same name, only one of the collection remains selected when clicked. Specifies a button that resets the entire form when clicked. Specifies a button that submits the form to the URL specified by the ACTION attribute of the <FORM> tag. Specifies a plain text box that can accept text characters and strings. Similar to a text box but it can span several lines and it enables the user to input multiple lines of text.

"checkbox"

"hidden"

"image"

"password" "radio" "reset" "submit" "text" "textarea"

The <SELECT> Tag

The <SELECT> tag is used for specifying drop-down, or list box controls. For items in these controls, the <SELECT> tag uses the <OPTION> tag to specify these items. Syntax <SELECT>...</SELECT> Attributes Attribute Purpose MUTIPLE Specifies that multiple items can be selected from the drop-down or list box.

NAME

Identifies the name of the drop-down or list box. Specifies how many entries of the <SELECT> tag should be displayed. As a rule of thumb, the SIZE determines whether the <SELECT> tag is a drop-down, or list box. If the SIZE="1" (by default it does) then the <SELECT> tag becomes a drop down box. If the value for SIZE is any other positive number, then the <SELECT> tag becomes a list box displaying (vertically) the items in the box. If there are more items in the list box than those displayed, then the box becomes scrollable.

SIZE

The <OPTION> Tag The <OPTION> tag is what specifies the entries, or list items in the <SELECT> tag. The general syntax for the option tag is: <OPTION>. All the words that follow the option tag become the text that is displayed on screen. The following table specifies the attributes of the <OPTION> tag. Attribute Purpose

Is a valueless attribute. Its purpose is to set one of the options as selected (the item is SELECTED highlighted). If no SELECT attribute exists in any of the option tags, then the first attribute is selected by default. VALUE Gives a value to the option tag. This value is submitted with the form if the option is selected.

Example The code in Listing B.1 can also be referenced off the accompanying CD.

Listing B.1 FORMD1.HTMA Demonstration of all the Form Controls <HTML> <HEAD> <TITLE>Sample Form</TITLE> </HEAD> <BODY BGCOLOR="#44AC55"> <FORM NAME="formme"> <FONT COLOR="blue" SIZE="+2">Checkboxes</FONT><BR> Small:<INPUT TYPE="checkbox" NAME="ch1"><BR> Medium:<INPUT TYPE="checkbox" NAME="ch1"><BR> Large:<INPUT TYPE="checkbox" NAME="ch1"><BR> <FONT COLOR="navy" SIZE="+2">Buttons</FONT><BR> <INPUT TYPE="button" NAME="b1" VALUE="click-me I">

<INPUT TYPE="button" NAME="b2" VALUE="click-me II"> <INPUT TYPE="button" NAME="b3" VALUE="click-me III"><BR> <FONT COLOR="tan" SIZE="+2">Hidden Fields</FONT><BR> <INPUT TYPE="hidden" VALUE="I am clickmeone" NAME="ha"> <INPUT TYPE="hidden" VALUE="I am clickmetoo" NAME="hb"> <INPUT TYPE="hidden" VALUE="I am clickmethree" NAME="hc"> <FONT COLOR="yellow" SIZE="+2">Image Controls</FONT><BR> <INPUT TYPE="image" NAME="im1" SRC="natback.gif"><BR CLEAR="all"> <FONT COLOR="aqua" SIZE="+2">Password Box</FONT><BR> <INPUT TYPE="password" NAME="p1" VALUE="fdgdgd"><BR> <FONT COLOR="fuchsia" SIZE="+2">Radio Buttons</FONT><BR> Yes <INPUT TYPE="radio" name="r1"> No <INPUT TYPE="radio" name="r1"> Maybe <INPUT TYPE="radio" name="r1"><BR> <FONT COLOR="maroon" SIZE=+2">Submit and Reset</FONT><BR> <INPUT TYPE="submit" NAME="haha" VALUE="submit me"> <INPUT TYPE="reset" NAME="boowho" VALUE="reset me"> <BR> <FONT COLOR="teal" SIZE="+2">Text box</FONT><BR> <INPUT TYPE="text" NAME="t1" VALUE="default value"> <BR></FORM></BODY></HTML>

Frames
Frames provide an efficient, convenient, and sharp way of presenting information in HTML documents. There are two frame systems: a collection of frames in a frameset, which replace normal HTML pages, and floating frames, which exist in normal HTML documents. Frame Sets Frame sets are used to replace normal HTML documents. With a frame set, a collection of frames that display different documents are displayed the browser screen. The <FRAMESET> tag is used to initiate and end the frame collection. The only tags that are allowed to be encapsulated in the <FRAMESET> tag is the <FRAME> tag and other <FRAMESET> tags. The <FRAME> tag specifies the properties for each individual frame. Frameset Syntax <FRAMESET> <FRAME> ...

</FRAMESET> Attributes for <FRAMESET> Attribute Required Purpose Specifies the number of columns in a frame set and their width, separated by commas. The column's length can specified either by pixels, a relative size, or as a percentage of a screen. For example, COLS="200,20%,*" specifies three columns. The first is 200 pixels wide, the second takes 20 percent of the leftover space on the screen, and the last takes the rest of the screen. Indicates whether a border for the frames should be present or not. Valid values for this attribute are Yes (specifying that a border is present), and No (specifying no border). The default value, if none is used is Yes. Specifies the length between each of the frames. This length also specifies the uniform length of the border (if one is present) Specifies the number of rows in a frame set and their height, separated by commas. The row's height can be specified in the same manner as columns (in pixels, screen percentage or a relative size). For example, ROWS="*,2*", specifies two rows. The first row is half the size of the second row, or takes 1/3 of the available space while, the second takes 2/3 of the space.

COLS

FRAMEBORDER

FRAMESPACING

ROWS

Either the attribute COLS or ROWS is specified when defining a frame set, but not both. Frame sets can be nested; which means one <FRAMESET>...</FRAMESET> can exist in another. The nested <FRAMESET> element can be defined differently as well (if the first was defined by COLS the second could be defined by COLS or ROWS making dynamic, richer looking pages (see the example section).

Attributes for <FRAME> Attribute FRAMEBORDER MARGINHEIGHT Required Purpose Indicates whether a border for the individual frame is present, or not. This attribute is identical to the attribute in the <FRAMESET> attribute table. Specifies the margin height of the frame in pixels.

MARGINWIDTH NAME NORESIZE SCROLLING SRC

Specifies the margin width of the frame in pixels. Identifies the frame so it can be accessed by other elements in HTML. An attribute without a specified value, that indicates that the frame will not be resizable by the user. Specifies whether the frames should be scrollable, or not (a scroll bar is on the right and bottom sides if the item is scrollable). Specifies the URL the frame should load and display.

The TARGET attribute


The TARGET attribute is the attribute that other HTML entities use to display their content (or hyperreferences) in different frames on the page. If a frame is named, frame1, then the TARGET attribute would access that frame by TARGET="frame1". The TARGET attribute works for the tags listed in the following table. Tag <A> TARGET's Function When the TARGET attribute is specified in an <A> tag, the link in the <A> tag is loaded in the specified window. If the <A> tag is in a frame and no TARGET is specified, the page is just loaded into the frame the link resides in.

When image's area, specified by the area tag, is clicked, the URL is loaded into the <AREA> window specified. If no window is specified, the URL is loaded into the frame with the image map that requested it. When the TARGET attribute is specified in the <BASE> tag, all the links on a page are directed to the frame specified by the TARGET attribute. This is a quick and short way <BASE> of directing all the links on a page to a specified frame instead of having to add the TARGET attribute to each one. If a tag does contain a different TARGET attribute, however, then the frame that the TARGET attribute references will receive that data. <FORM> When the TARGET attribute is in the <FORM> tag, the results returned by submitting the form will be sent to the frame specified by TARGET.

There are also special reserved names that can be used by the TARGET attribute to reference different frames on the screen. The following table shows the reserved names that can be used with the TARGET attribute. Special Value Function "blank" This value for the TARGET attribute specifies that the content requested by the tag, which contains the TARGET attribute, be loaded in a new window (new browser).

"parent" "self" "top"

This value indicates that the content, referenced by the element containing the TARGET attribute, is to be loaded into the frame's parent window. This value indicates that the content should be loaded into its own window. This value indicates that the content should be loaded into the topmost frame. The "_top" value is not functioning properly in the beta 1 version of Internet Explorer 3.0

If a name specified by the target attribute does not exist, or is not on of the special names, a new browser with the URL specified by the tag with the TARGET attribute is loaded.

Examples The examples in Listings B.2 through B.6 demonstrate how frames are used, these files can also be found on the accompanying CD under their respective name. All these files should be in the same directory to work properly.

Listing B.2 QAB.HTMThe Main Frames Page <HTML> <HEAD> <TITLE>Demonstrations of Frames</TITLE> </HEAD> <BODY BGCOLOR="cornsilk"> <FRAMESET COLS="*,350" FRAMESPACING="5"> <FRAME SRC="default1.htm" SCROLLING="no" NAME="left1"> <FRAMESET ROWS="*,100"> <FRAME SRC="default2.htm" SCROLLING="no" NAME="right1"> <FRAME SRC="menu.htm" SCROLLING="no" NAME="right2"> </FRAMESET> </FRAMESET> </BODY></HTML>

Listing B.3 MENU.HTMThe Main Menu-Navigation Bar <BODY BGCOLOR="slateblue" TOPMARGIN="0" LEFTMARGIN="0"> <IMG SRC="map.jpg" HEIGHT="100" WIDTH="350" USEMAP="#mapone"> <MAP NAME="mapone"> <AREA SHAPE="poly" COORDS="0,0,0,99,128,99,66,0" HREF="default1.htm" target="right1"> <AREA SHAPE="poly" COORDS="70,0,185,0,258,99,132,99" HREF="default2.htm" TARGET="left1"> <AREA SHAPE="circ" COORDS="302,53,33" HREF="default3.htm" TARGET="left1"> </MAP> </BODY>

Listing B.4 DEFAULT1.HTMThe Default Screen for the "left1" Frame <BODY BGCOLOR="gold" TEXT="chocolate"> <FONT SIZE="+3" COLOR="violet">This is the default page for the first frame. Note the diversity of color names</FONT> in the source. </BODY>

Listing B.5 DEFAULT2.HTMDefault for the "right1" Frame <BODY BGCOLOR="seagreen" TEXT="moccasin"> This is another frame. <A HREF="blank.htm" TARGET="right2">This link clears the menu</ A><BR> <A HREF="menu.htm" TARGET="right2">This brings it back</A> <HR> </BODY>

Listing B.6 DEFAULT3.HTMThe Default Screen 3, When the User Clicks Item 3 in the Navigation Bar <BODY BGCOLOR="midnightblue" TEXT="mistyrose"> <H1> This is another test frames. How does it look?? </H1> </BODY>

The <Hn> Tag


Purpose The <Hn> tags are tags that specify headings for an HTML page, where n is a number between 1 and 7 (7 being the smallest). Syntax <H1>...</H1> <H2>...</H2> <H3>...</H3> <H4>...</H4> <H5>...</H5> <H6>...</H6> <H7>...</H7> Attributes Attribute Required Purpose ALIGN Specifies the alignment of the Header. ALIGN can have the values, "left", "right", and "center".

Example <H1 ALIGN="center">Outline</H1>

<H2>Introduction</H2> <H3>Purpose</H3> <H3>Doscussion</H3> <H2>Methods</H2> <H3>Resourse</H3> <H3>Procedure</H3> <H2>Results</H2> <H2>Conclusions</H2>

The <HR> Tag


Purpose The <HR> tag is used to specify a horizontal rule, or divider across the page. Syntax <HR> Attributes Attribute ALIGN Required Purpose Specifies the alignment of the horizontal rule. The value for ALIGN can be either "right", "left", or "center". The horizontal rule is centered by default. Specifies the color of the horizontal line. The color can be one of several supported color names, or a hexadecimal value. Refer to the <BODY> section of this appendix for more information on colors and color names. Specifies that the rule does not have any shading (or 3-D look). This attribute does not have a value. Specifies the height of the horizontal rule. The value for this attribute is in pixels. Specifies the length of the horizontal rule. The value for WIDTH can either be in pixels, or a percentage of the screen (for example, SIZE="50%" would be 50 percent of the screen.)

COLOR

NOSHADE SIZE

WIDTH

Example <HR WIDTH="20%" COLOR="red" NOSHADE> <HR> <HR SIZE="25" COLOR="LIME">

The <I> Tag


Purpose The <I> tag renders text in italics and functions the same as the <DFN>, <EM> and other tags. Syntax <I>...</I> Attributes None. Example <I>This text is in Italics</I><BR> <EM>So is this.</EM>

The <IMG> Tag


Purpose The <IMG> tag allows the insertion of graphics images, animations, and animated GIF images. Syntax <IMG> Attributes Attribute Required Purpose

ALIGN

Specifies the alignment of text relative to the image or vice versa, depending on the value. The values "bottom", "middle", or "top" specify the alignment of text respective to the name of the value. The values right or left specify the alignment of the image on the page. The latter two values also permit text to flow around the image. Specifies an alternative text to display if the user chooses not to display graphics. Also, the string contained as a value in the ALT attribute is what gets displayed when a user points at a picture. Draws a uniform border around the image. The values for the BORDER are measured in pixels. Is a valueless attribute. This attribute can be used when an animation (. AVI) file is displayed. When the CONTROLS attribute is used, a set of video controls is displayed under the animation. Used to display an animation on-screen usually with the .AVI extension. The value for this attribute can be the name of a file, or a URL of a file. Specifies the height of the image in pixels. If the height specified is not the original height of the image, then Internet Explorer scales the image to the specified height. Specifies the horizontal spacing, or offset of the image on its right ad left sides. Specifies that the image is a clickable imagemap. It sends the coordinates the user clicks to the server where the program is specified that handles these coordinates, Specifies how many times the animation should loop. The values for this attribute can be a number or infinite, meaning a continuous loop. Specifies the name of the image to be displayed. Several formats are supported by explorer. Some are .BMP, .GIF, and .JPG also proposed is the .PNG format. The specified location can either be a filename, or a URL pointing to a file. Specifies when the animation should start after the image is loaded. The values for this attribute are fileopen, or mouseover. Fileopen indicates that the animation should start playing when the animation is done loading. Mouseover indicates that the image will start playing when the user points the mouse at the animation. Both attributes can be used together. Specifies the location (name) of a client-side imagemap to use with the image. The image map is usually in the same document and is called by the value "#name" where name is the name of the image map (see the client side image map section for more information.)

ALT

BORDER

CONTROLS

DYNSRC

HEIGHT

HSPACE

ISMAP

LOOP

SRC

START

USEMAP

VSPACE

Specifies, in pixels, the top and bottom offset space of the image. This similar to the HSPACE attribute except it specifies widths for the top and the bottom of the image. Specifies the width, in pixels, of the image. If the width specified is not the original size of the image, then it is scaled to the size specified.

WIDTH

Either the DYNSRC, or the SRC attribute is required but not both. However, both can be used simultaneously.

Example <P>The following displays a normal image:</P><BR> <IMG SRC="test.gif" SIZE="100" HEIGHT="100"><BR> <P>The following image is the same image but half the size:</P> <IMG SRC="test.gif" SIZE="50" HEIGHT="50"><BR> <P>Text is flowed around <IMG SRC="hi.gif" ALIGN="left"> this image if you get what I am saying</P> <BR><P>This is an animation with controls that will start when it is finished downloading and will start afterwards when you move the mouse over it:</P><BR> <IMG DYNSRC="ball.avi" START="fileopen,mouseover">

The <ISINDEX> Tag


Purpose The <ISINDEX> tag is used to create a simple input box, which serves the purpose of being a search engine powered by some program.

Syntax <ISINDEX> Attributes Attribute Required Purpose ACTION Specifies the location of the program used to process the information entered into ISINDEX box. Specifies what the prompt name should be given to the <ISINDEX> input box. If no name is specified, then the prompt "You can search this index. Type the keyword(s)you want to search for:" appears by default.

PROMPT

Example <ISINDEX ACTION="http://www.place.com/cgi-bin/myengine.cgi" PROMPT="Enter Words to search for:">

The <KBD> Tag


Purpose The <KBD> tag is used to logically represent what one would type on a keyboard (instructional). Text encapsulated by this tag is rendered in a fixed-width font and is in bold. Syntax <KBD>...</KBD> Attributes None. Example You type the words: <KBD>cd ..</KBD> then enter.

The <LISTING> Tag


Purpose

The <LISTING> tag is used to render text in a small, fixed-width font that resembles a code listing. No tags are recognized within the context of the <LISTING> tag and line breaks are natural (no special tags are required to insert line breaks). Syntax <LISTING>...</LISTING> Attributes None. Example An example FORTRAN 77 program: <LISTING> program test print*,'This is a texs' end </LISTING>

Lists
Definition Lists Definition lists are used to define a list of terms. There are three parts to a definition list. These are shown in the following syntax. The <DT> tag is used to specify the terms in the definition list, and the <DD> tag is the Definition Data or the defining of the term specified by <DT>. The definition terms are put on one line and the definition is on the next line, slightly indented. Syntax <DL> <DT>...</DT><DD>...</DD> ...

</DL> Attributes None.

Although the </DT> and the </DD> tags are not required for encapsulating their respective text, it is a good idea to include them for clarity and to avoid confusion.

Directory Lists The <DIR> tag is used to specify a directory of items. Each entry is displayed in a single column. The <LI> tag is used for specifying the entries in the directory list. Syntax <DIR> <LI>...</LI> ... </DIR> Attributes None. Menu Lists The menu lists create lists similar to the <DIR> lists except there is no limit on characters. The <LI> tag is used to indicate the individual entries inside the <MENU> tag. Technically, there is no difference between <MENU> and <DIR> lists. Syntax <MENU>

<LI>...</LI> ... </MENU> Attributes None. Ordered Lists Ordered lists are lists whose entries are preceded with numbers, letters, or Roman Numerals whose list number (or what have you) increases when subsequent entries are specified. The <LI> tag is used to specify each of the entries in the ordered list. Syntax <OL> <LI>...</LI> ... </OL> Attributes Attribute Required Purpose Specifies a start number where the list should start. If the type of list is not a number, then the list starts out with the nth item in order (where n is the start value specified). For example, if the number type was a roman numeral, and START="3", the value that would be displayed in the list for the first item is III. Specifies what type of numbering system to use. The following table lists the listing types.

START

TYPE

TYPE Value Renders As "1" "A" Renders the list entries as normal Arabic numerals (1, 2, 3, etc) Renders the list entries as capital letters (if there are more than 26 entries, then the value goes to AA, AB etc. but if the value for START exceeds 702 then the items are rendered as a digit again.

"a" "I" "i"

Renders list entries as lowercase letters. The same situation for number limits is the same as uppercase letters. Renders list entries as uppercase Roman numerals. If the value for uppercase Roman numerals exceeds 3999 (MMMCXCIX) then the style resumes as digits. Renders list entries aslowercase Roman numerals. The same situation for number limits is the same as uppercase Roman numerals.

Attributes for <LI> Attribute Required Purpose TYPE Specifies which type of list-number should be used (valid values are in the previous table.) Specifies the starting value of the list item. The value that is initially specified in the list and the value that is set in the <LI> tag are independent. The <LI> tag's value has precedence over the <OL>'s START value. Also, the list proceeds from the value specified by the <LI> tag.

VALUE

Unordered Lists Unordered lists are lists, preceded by bullets and used when order is of no particular importance. The <LI> tags are used in the <UL> list denote the different entries. Syntax <OL> <LI>...</LI> ... </OL> Attributes None. Example <HTML> <HEAD> <TITLE>Demo 2 of Body demonstration</TITLE> </HEAD>

<BODY BACKGROUND="natback.gif" TEXT="#0000FF" > <H1 ALIGN="CENTER">Demo of ordered lists</H1> <H3>This is a definition list</H3> <DL> <DT>Hydrogen</DT><DD>Earths lightest gas. A proton in ioonized form</DD> <DT>Helium</DT><DD>A noble gas, second lightest</DD> <DT>Clorine</DT><DD>A Halide. Very reactive with alkaline metals</DD> <DT>Carbon</DT><DD>A non-metal whose presence indicates an organic material. </DD> </DL> <H3>This is a directory list</H3> <DIR> <LI>Sam Smith</LI><LI>Joe Jones</LI> <LI>Al Able</LI> <LI>Billy Bob</LI> <LI>dsdsdsdsdsdsdsdsdsdsdsdsds this has more than 20 chars.</ LI> </DIR> <H3>This is a menu list</H3> <MENU> <LI>Soup</LI> <LI>Beef</LI> <LI>Veggies</LI> <LI>Milk</LI> </MENU> <H3>This is an ordered list with Uppercase letters</H3> <OL TYPE="A" START="698"> <LI>This the first entry starting at 698</LI> <LI>Second (699)</LI> <LI>Third (700)</LI> <LI>Fourth (701)</LI> <LI>Fifth (702)</LI> <LI>What did I tell you?</LI> </OL> <H3>This is an unordered list</H3> <UL> <LI>Strawberries</LI> <LI>Tires</LI> <LI>Baseball gloves</LI> <LI>Scissors</LI> <LI>Pillows</LI> </UL> </BODY></HTML>

The <MARQUEE> Tag


Purpose The <MARQUEE> tag enables the user to create a text marquee that is scrollable across the screen. This is one of the 'elegant' tags of the Internet Explorer 3.0 HTML collection. Syntax <MARQUEE>...</MARQUEE> Attributes Attribute Required Purpose Specifies the alignment of the text in the marquee. The value "top" aligns the text of the marquee with the top of the marquee container (where the text of the marquee is. ) The 'bottom" value aligns the marquee with the bottom of the container and the "middle" value aligns the text with the middle. The text is middle aligned by default. Indicates how the text of the marquee should behave. The value "scroll" (also the default behavior) makes the text repeatedly scroll on and off the screen. The value "slide" causes the text to scroll in on one side and stay. The value "alternate" causes the text to bounce back and forth within the marquee. Specifies the background color of the marquee. The value for BGCOLOR is specified the same way as the BGCOLOR attribute for the <BODY> tag (see the <BODY> tag). Specifies the direction the marquee scrolls. Valid values are RIGHT and LEFT. The default value is LEFT (from left to right). Specifies the height of the marquee area, in pixels, or a percentage of the screen (such as HEIGHT="500" for pixels or HEIGHT="20%" for percentage. Indicates the left and right marginal distance, or offset of the marquee. Specifies the number of times the marquee perform whatever action specified by behavior. Valid values are numbers specifying how many times the marquee should loop, or the word "infinite" specifying that their is no end to the looping. Specifies the number of pixels between each successive draw of marquee text. Values are in pixels.

ALIGN

BEHAVIOR

BGCOLOR

DIRECTION

HEIGHT

HSPACE

LOOP

SCROLLAMOUNT

SCROLLDELAY VSPACE WIDTH

Specifies the time of each successive draw of the marquee text in milliseconds. Specifies the top and bottom marginal distance or offset of the marquees area. Values are in pixels. Specifies the width of the marquee, in pixels, or as a percentage of the screen (similar to height).

You can make symbol type graphics scroll in a marquee by using a symbol font, such as Wingdings, for the text scrolling in a marquee. For example: <FONT FACE="wingdings"><MARQUEE SCROLL="left">Q</MARQUEE></FONT>.

It is not a good idea too encapsulate tags inside the marquee tag. It's best to nest the marquee in the different rendering tags you use. For instance: <I><MARQUEE>Hi Y'all</MARQUEE></I> is preferable. Some tags cause the marquee not to scroll when they are used. For information about putting graphics and other elegant items in marquees, read about the Active-X Marquee which will be covered in Chapters 2 and 11.

Example <MARQUEE DIRECTION="right" BEHAVIOR="slide" SCROLLAMOUNT="45" [ccc] SCROLLDELAY="4" BGCOLOR="blue"><FONT COLOR="white">This text [ccc] scrolls fast.</MARQUEE>

The <NOBR> Tag


Purpose The <NOBR> is used to force a line to remain together with out breaking (where a break would normally occur).

Syntax <NOBR>...</NOBR> Attributes None. Example <NOBR> All of this text will remain on one line, regardless of the [ccc] size of the browser.</NOBR>

Objects
For a detailed explanation of Microsoft Internet Explorer's object model, see Chapter 11.

The <P> Tag


Purpose The <P> tag is used to separate paragraphs of text. A line break also occurs between every use of the <P> tag. Syntax <P>...</P> or just <P> Attributes Attribute Required Purpose ALIGN Specifies the alignment of the paragraph text. Valid values are "right", or "left".

Example <P ALIGN="left"> This text is left aligned</P>

<P ALIGN="right"> This test is right aligned </P>

The <PLAINTEXT> Tag


Purpose The <PLAINTEXT> tag renders text similar to the <LISTING> and <XMP> tags. All the text that is surrounded by the <PLAINTEXT> tag is rendered in a fixed-width font and no tags are recognized inside the <PLAINTEXT> tag. Syntax <PLAINTEXT>...</PLAINTEXT> Attributes None. Example <PLAINTEXT> This is plain text</PLAINTEXT>

The <PRE> Tag


Purpose The <PRE> tag renders the text it surrounds in a fixed-width font. Additionally, natural line breaks are allowed and some tags (such as the <A> tag) are allowed to be used within the <PRE> tag. Syntax <PRE>...</PRE> Attributes None. Example <PRE> This is line one

. . . This is line #x This is line #<A HREF="three.html">x + 1</A> </PRE>

The <S> Tag


Purpose The <S> tag renders the text it surrounds in a strike-out style, in which a line is run through the middle of the encapsulated text. Syntax <S>...</S> Attributes None. Example <S>not needed</S>

The <SAMP> Tag


Purpose The <SAMP> tag is used to make the text it surrounds look like a code listing. Syntax <SAMP>...</SAMP> Attributes

None. Example <SAMP>print "A test"</SAMP>

The <SCRIPT> tag


The <SCRIPT> tag is fully covered in Chapters 2 and 11.

The <SMALL> Tag


Purpose The <SMALL> tag is used to render the text it encapsulates in a size smaller then the normal text. Syntax <SMALL>...</SMALL> Attributes None. Example <SMALL>This is the fine print</SMALL>

The <STRIKE> Tag


Purpose The <STRIKE> tag does the exact same thing the <S> tag does. See the previous <S> tag entry. Example <STRIKE>this works the same as the &lt;S&gt; tag. </STRIKE>

The <STRONG> Tag


Purpose The <STRONG> tag is another tag that renders the text it surrounds in bold. It is used to logically

represent a strong emphasis. Syntax <STRONG>...</STRONG> Attributes None. Example The victim is <STRONG>her</STRONG>.

The <SUB> Tag


Purpose The <SUB> tag is used to render the text it encapsulates as a subscript. Syntax <SUB>...</SUB> Attributes None. Example The chemical formula for the combustion of octane is: C<SUB>3</SUB>H<SUB>8</SUB> + 5O<SUB>2</SUB> = 4H<SUB>2</SUB>O [ccc] + 3CO<SUB>2</SUB>

The <SUP> Tag


Purpose The <SUP> tag renders the text it surrounds as a superscript. Syntax

<SUP>...</SUP> Attributes None. Example x<SUP>y</SUP> = y<SUP>x</SUP> <BR> for how many values of x and y?

Tables
Tables are one of the extensions to HTML that have been around the longest. Although tables are still not a standard, they are quite close and probably will not change in regards to syntax. Tables were first implemented by Netscape Navigator and since then improved upon by Internet Explorer (support for background and frame colors and stricter support for the HTML 3.0 Table Model). There are two different methods for making a table. The first uses basic tags defining rows and columns. The second method uses rows and columns but also treats the table as three parts: the header, the body, and the footer. The Simple Table This section is an overview of the basic tags and attributes for tables, excluding the additional attributes covered in the new HTML 3 table model. These table extensions and additional tags and attributes will be covered in the next section. The simple table consists of a groups of rows that can contain several cells. The table's content is defined by rows and then by all the cells on that row.
Syntax

<TABLE> <CAPTION>...</CAPTION> <TR><TH>...</TH><TD>...</TD>...</TR> ... </TABLE>


The <TABLE> Tag

The <TABLE> tag is what specifies the beginning and end of a table. All the information about rows, columns, and other information must be inside the table tags. Below are the attributes for the <TABLE> tag. These attributes can also be used for the <TD>, <TH>, and <TR> (except for the BORDER attribute). These attributes are inheritable, which means that if the attribute is specified in the <TABLE> tag, it is also used by the <TR>, <TD>, and <TH> tags unless they have a different value for that attribute. If the <TR>, <TD>, and <TH> tags have attribute values different from their parent (higher) tags, then that attribute is used instead. Attribute Required Purpose Specifies the alignment of the text in the table cells. Valid values are "left", "right" and "center". By default, the <TABLE>, <TD>, and <TR> tags have left aligned text and the <TH> tag's text is centered. Specifies a background image to be displayed in the table's cells. Valid values are filenames, or URLS that point to a displayable image. Specifies a background color for the table cells. Valid values are one of several color names or a color defined in hexadecimal (see the <BODY> tag for more information). Specifies the border color to be used. When this attribute is used, the table's border and the border between the cells become the specified color and are no longer 3-D. Valid colors are one of the supported color names, or a hexadecimal #rrggbb value (see the <BODY> tag for more details). Sets the color for the upper right-hand border of a frame. Colors are specified the same way as in BORDERCOLOR. Sets the color for the lower left-hand border of the frame. Colors are specified the same way as in BORDERCOLOR. Specifies the vertical alignment of a table/cell/cell group. Valid values are "top", and "bottom". The value, "top" aligns the cell text with the topmost portion of the cell and the "bottom" value aligns the cell's text with the bottom most portion of the cell.

ALIGN

BACKGROUND

BGCOLOR

BORDERCOLOR

BORDERCOLORDARK BORDERCOLORLIGHT

VALIGN

The following table contains attributes which are specific to the <TABLE> tag: Attribute Required Purpose Specifies the uniform width of the table's outer border in pixels. If this attribute is not present, the value is "0" (no border). If the attribute is present but has no value, the width of the border becomes on pixel. Any other value for the border is in pixels (for example, BORDER="3" sets a border that has a uniform width of 3 pixels).

BORDER

CELLPADDING

Specifies the amount of uniform margin space (space separating the cell text from its borders) in pixels. Specifies the uniform spacing of the individual cells, in pixels. If there is a border present,the value for this attribute is the uniform size of the border between the cells, and between the cells and the border. Specifies the total screen height the table takes up. This value can be in pixels but values using percentages of the screen are more useful (in other words, HEIGHT="88%" would take up 88 percent of a screen lengthwise). Specifies the total screen width the table should take up. This value can be in pixels but is more useful as a percentage of the screen (such as, WIDTH="90%" would take up 90 percent of the horizontal screen space).

CELLSPACING

HEIGHT

WIDTH

The <CAPTION> tag The caption tag is used to specify a caption for the table. The <CAPTION> tag has only one attribute, ALIGN, used to specify the alignment of the caption text. Valid values are "top", "bottom", "left", and "right". Each value indicates its respective location to the table. The <TR> tag The <TR> tag defines a row group. All the cells in the row group are placed horizontally (side-byside) on the screen. The tag's cell data, and the cell tags (<TD> and <TH>) go inside the <TR> tag. The <TD> and <TH> Tags The <TD> and <TH> tags are used to specify the cells in a table; they are encapsulated in the <TR> tags. The <TD> is a normal table data cell and is rendered in normal text, by default. The <TH> tag is a table-cell header tag and is rendered in bold and centered, by default. There are several attributes specific to the <TD> and <TH> tags and they are listed in the following table. Attribute ALIGN COLSPAN Required Purpose ALIGN specifies the alignment of the text in the cell. Valid values are "right", "left", and "center". COLSPAN specifies the amount of columns a cell should span (for example, COLSPAN="2" would make the cell span over two columns). HEIGHT specifies the height of a table's cell in pixels. All cells on the same row will be stretched to the height specified (if there is more than one height attribute on a row, the largest height will be used as the height of all the cells in the same row).

HEIGHT

NOWRAP ROWSPAN

NOWRAP indicates all the text in the cell should remain on one line (this attribute requires no value). ROWSPAN specifies the number of rows a cell should span (in other words, ROWSPAN="3" would make a cell span over three rows). VALIGN specifies the vertical alignment of the text in the cell relative to the cell. Valid values are Top (text is aligned with the top of the cell), Bottom (text is aligned with the bottom of the cell), Middle (text is aligned with the middle of the cell), and Baseline (text is aligned with the baseline of the cell, all the text in a row of cells is on a straight line). WIDTH specifies the width of a table's cell, and incidentally, the width of its entire column (the column stretches to the longest width specified).

VALIGN

WIDTH

The VALIGN attribute can be used in both the <TR>, <TD>, and <TH> attributes.

Advanced Table Layouts This section covers the more in-depth tags of the HTML 3.0 table model covered by Internet Explorer 3.0. These elements include table header, body, and footer elements, as well as attributes for frame and border layout, and control over column groups instead of row groups.
Header-Body-Footer Based Layout

It's possible to design a table with Header/Body/Footer sections in mind. To do this three tags are introduced: <THEAD>, <TBODY>, and <TFOOT>. These improve upon the simple table model. All the original cell and row tags can be encapsulated in the <THEAD>, <TFOOT>, and <TBODY> tags. There are also two new attributes introduced to the <TABLE> tag: FRAME, and RULING. These will be discussed in the attributes section. Syntax <TABLE> <THEAD>...</THEAD> <TBODY>...</TBODY> <TFOOT>...</TFOOT>

</TABLE> Using this method, if no sections (header, body , footer) are specified, just a table body exists. However, if <THEAD> or <TFOOT> are used to define their respective sections, then <TBODY> must be included. The FRAME and RULES Attributes for <TABLE> The FRAME attribute for the <TABLE> specifies which sides of the border (if any) are to be rendered. The following table shows all the valid values for specifying which border frames to render. FRAME Value Function "void" "above" "below" "hsides" "lhs" "rhs" "vsides" "box" "border" No outside borders of the table are displayed if this value is used Only the top side of the border is rendered Only the bottom side of the border is rendered Only the left and right sides of the frame are rendered Only the left side of the border is displayed Only the right hand of the table's border is displayed Only the top and bottom borders are displayed All four sides of the frame are displayed The same as "box"

The RULES attribute for the <TABLE> tag specifies which interior borders (borders between cells and the major sections of the table) should be rendered. The table below shows all the valid values for designating which interior rulings to render. RULES Value Function "all" "groups" "none" "cols" "rows" All interior rules are displayed. Interior rules are placed between each row group and each column group. The three row groups are specified by the <THEAD>, <TBODY>, and <TFOOT> tags (see the next section for column groups). No interior rules are drawn. This functions similarly to the "groups" value except vertical rules are drawn for all columns. This functions similarly to the "rows" value except horizontal rules are drawn between every row.

The <TBODY>-<THEAD>-<TFOOT> style must be used for RULES and FRAMES to work.

Controlling Alignment by Columns

In addition to having properties for groups of rows in tables, you can also have column groups in tables that can change the alignment and size of groups of columns. The <COLGROUP> tag is used to encapsulate a collection of column groups which are indicated by <COL>. Syntax <TABLE> <COLGROUP> <COL> ... </COLGROUP> ... <THEAD>...</THEAD> ... </TABLE> The <COLGROUP> can be used to set alignments on column groups, or the <COL> tag, according to the attributes listed below. The <COL> tags have inheritance and override the attributes specified by its parent <COLGROUP> tag. The <COL> tag inside the <COLGROUP> tag is not required, because the spanning for a column group can be specified in the <COLGROUP> tag; the <COL> tag is used for control of individual column groups, for alignment, and width. Both the <COLGROUP> and the <COL> tags support the attributes in the following table. Attributes for <COLGROUP> and <COLS> Attribute Required Purpose ALIGN Specifies the alignment of the text in a column group. Valid values are "left" aligned, "right" aligned, and "center" aligned.

SPAN WIDTH

Indicates how may columns the <COLGROUP> or <COL> spans. For instance, if SPAN="2" then the column group consists of two columns. Specifies the width of the column group (this attribute is apparently not implemented in the beta 1 version of Internet Explorer 3.0).

<COL> tags and <COLGROUP> tags are cumulative. For example, if a column group had a column span of 2 (<COLGROUP SPAN="2">) and another column group had two <COL> elements with a span of 1 (<COLGROUP><COL SPAN=1><COL SPAN=1></COLGROUP>), then four columns have been used already. If a column group has a SPAN value and it also contains <COL> elements with a SPAN value, then the SPAN values for the <COL> tag are used and the value for the <COLGROUP> is ignored.

Examples Listing B.7 invokes both the methods of simple tables and tables with column groups, frames and rules. This example can be found on the accompanying CD.

Listing B.7 TABLESTF1.HTMThis is an Example of Two Tables <HTML> <HEAD> <TITLE>A Demonstration of tables</TITLE> </HEAD> <BODY BGCOLOR="#345678"> <H2>A simple table using various alignment, formatting and coloring tags.</H2> <!-- This is table 1 --> <TABLE BORDER="1" BGCOLOR="tan"> <TR> <TD ROWSPAN=2 BGCOLOR="black"></TD> <TH COLSPAN="4" BGCOLOR="white">Revenue (in 10<SUP>6</SUP> $'s) </TH> </TR> <TR>

<TH COLSPAN=2 BGCOLOR="yellow">First Half</TH> <TH COLSPAN=2 BGCOLOR="yellow">Second Half</TH> </TR> <TR><TH WIDTH="100" BGCOLOR="goldenrod">Year</TD> <TH BGCOLOR="gold">First Quarter</TH> <TH BGCOLOR="gold">Second Quarter</TH> <TH BGCOLOR="gold">Third Quarter</TH> <TH BGCOLOR="gold">Fourth Quarter</TH> </TR> <TR> <TD BGCOLOR="green">1994</TD> <TD BGCOLOR="#3737373"><I>30</I></TD> <TD BGCOLOR="#3737373"><I>30</I></TD> <TD BGCOLOR="#3737373"><I>23</I></TD> <TD BGCOLOR="#3737373"><I>44</I></TD> </TR> <TR> <TD BGCOLOR="green">1995</TD> <TD BGCOLOR="#3737373"><I>31</I></TD> <TD BGCOLOR="#3737373"><I>33</I></TD> <TD BGCOLOR="#3737373"><I>23</I></TD> <TD BGCOLOR="#3737373"><I>45</I></TD> </TR> <TR> <TD BGCOLOR="green">1996</TD> <TD BGCOLOR="#3737373"><I>29</I></TD> <TD BGCOLOR="#3737373"><I>33</I></TD> <TD BGCOLOR="#3737373"><I>23</I></TD> <TD BGCOLOR="#3737373"><I>56</I></TD> </TR> </TABLE> <!-- This is end of table 1 --> <BR CLEAR="all"> <HR> <TABLE BORDER="3" CELLSPACING=2 CELLPADDING=3" RULES="groups" [ccc] BGCOLOR="lightblue" WIDTH="100%"> <CAPTION ALIGN="top"> <FONT SIZE="-1" FACE="Comic Sans MS" COLOR="red"> A more complex table utilizing the RULES, FRAME, &lt; COLGROUP&gt; , &lt;COL&gt;, and other entities of a table.</FONT> </CAPTION> <COLGROUP SPAN="1" ALIGN="center"> <COLGROUP> <COL SPAN="3" ALIGN="center"> </COLGROUP>

<COLGROUP SPAN="1"> <COLGROUP SPAN="2" ALIGN="center"> <THEAD> <TR BGCOLOR="aquamarine"> <TH>Product #</TH> <TH>Department A</TH> <TH>Department B</TH> <TH>Department C</TH> <TH>Total #</TH> <TH WIDTH="100">Good</TH> <TH WIDTH="100">Defective</TH> </TR> </THEAD> <TBODY> <TR> <TD BGCOLOR="aqua" BORDERCOLOR="aqua">225A</TD> <TD BGCOLOR="lightblue">5</TD> <TD BGCOLOR="lightblue">6</TD> <TD BGCOLOR="lightblue">7</TD> <TD BGCOLOR="lightblue">18</TD> <TD BGCOLOR="lightblue">10</TD> <TD BGCOLOR="lightblue">8</TD> </TR> <TR> <TD BGCOLOR="aqua" BORDERCOLOR="aqua">761C</TD> <TD BGCOLOR="lightblue">2</TD> <TD BGCOLOR="lightblue">4</TD> <TD BGCOLOR="lightblue">5</TD> <TD BGCOLOR="lightblue">11</TD> <TD BGCOLOR="lightblue">10</TD> <TD BGCOLOR="lightblue">1</TD> </TR> <TR> <TD BGCOLOR="aqua" BORDERCOLOR="aqua">3999</TD> <TD BGCOLOR="lightblue">1</TD> <TD BGCOLOR="lightblue">0</TD> <TD BGCOLOR="lightblue">1</TD> <TD BGCOLOR="lightblue">2</TD> <TD BGCOLOR="lightblue">1</TD> <TD BGCOLOR="lightblue">1</TD> </TR> <TR> <TD BGCOLOR="aqua" BORDERCOLOR="aqua">702</TD> <TD BGCOLOR="lightblue">5</TD> <TD BGCOLOR="lightblue">5</TD> <TD BGCOLOR="lightblue">5</TD>

<TD BGCOLOR="lightblue">15</TD> <TD BGCOLOR="lightblue">5</TD> <TD BGCOLOR="lightblue">10</TD> </TR> <TR> <TD BGCOLOR="aqua" BORDERCOLOR="aqua">?56</TD> <TD BGCOLOR="lightblue">25</TD> <TD BGCOLOR="lightblue">25</TD> <TD BGCOLOR="lightblue">6</TD> <TD BGCOLOR="lightblue">56</TD> <TD BGCOLOR="lightblue">50</TD> <TD BGCOLOR="lightblue">6</TD> </TR> <TR> <TD BGCOLOR="aqua" BORDERCOLOR="aqua">1123</TD> <TD BGCOLOR="lightblue">11</TD> <TD BGCOLOR="lightblue">23</TD> <TD BGCOLOR="lightblue">0</TD> <TD BGCOLOR="lightblue">34</TD> <TD BGCOLOR="lightblue">30</TD> <TD BGCOLOR="lightblue">4</TD> </TR> </TBODY></TABLE></BODY></HTML>

The <TT> Tag


Purpose The <TT> tag renders encapsulated text in a typewriter type font. Syntax <TT>...</TT> Attributes None. Example <TT>Demonstration of the &lt;TT&gt; tag.</TT>

The <U> Tag

Purpose The <U> tag is used to underline the text it encapsulates. Syntax <U>...</U> Attributes None. Example <U>This is not a link</U>

The <VAR> Tag


Purpose The <VAR> tag is used to surround text that logically represents a variable. The text rendered is in italics. Syntax <VAR>...</VAR> Attributes None. Example

The <WBR> Tag


Purpose The <WBR> tag is used to insert a soft word break inside a <NOBR> tag. Syntax <WBR>

Attributes None. Example <NOBR> This line will not break. Except, <WBR> here.</NOBR>

The <XMP> Tag


Purpose The <XMP> tag is used to render text in a fixed-width font. This tag is similar to the <LISTING> tag.

The <XMP>, <LISTING>, and <PLAINTEXT> tags are considered legacy tags and probably will not be included in future versions of the HTML draft or in Internet Explorer 3.0.

Syntax <XMP>...</XMP> Attributes None. Example <XMP> This is MyPoem() first line here; second line here; third line here; End MyPooem

</XMP>

Miscellaneous Tags
The <BASE> Tag
Purpose The <BASE> tag is used to specify the base URL of the document in which the tag resides. This mechanism is especially useful when the file that contains the <BASE> tag is taken out of context. Syntax <BASE> Attributes Attribute Required Purpose HREF Specifies the URL of the document in which the <BASE> tag resides. The full URL is used.

Example A file called welcome.html located at www.nm.org would have the following base tag: <BASE HREF="http://www.nm.org/welcome.html">

The <BASEFONT> Tag


Purpose The <BASEFONT> tag is used to specify the base, or normal, size of the text that is normally used on the screen. Syntax <BASEFONT> Attributes

Attribute Required Purpose Specifies the new color of the text. The color is specified by one of several color names (noted in the <BODY> tag section), or by a hexadecimal value in the form of #RRGGBB (where RR, GG, and BB is a hexadecimal number from 0 to FF (255) in red, green and blue respectively). Specifies the new font for the text being encapsulated. Whether the font is shown or not, depends on whether it is available on the user's system. Some common fonts are listed in the next table. You can specify multiple font names in case the user does not have the first specified font (for example, if FACE="Times, Arial, Bahamas" the Times font will be used, if it's not available, the Arial font can be used, and so on). There is technically no limit to the number of alternative fonts you can specify. Specifies the size of the text surrounded. This can be a size relative to the base size (1 by default) or a new size (from 17). A relative size to the default size (3) can also be used (in other words, SIZE="+2" means two sizes larger than the default size or "5" and SIZE="-1" is one size smaller than the default size of "2").

COLOR

FACE

SIZE

Example This size specified by the following <BASEFONT> is size 4. <BASEFONT SIZE="4" FACE="Sans"> The size specified by <BASEFONT> below is also 4 but with a relative size. <BASEFONT SIZE="+1" COLOR="pink">

The <BGSOUND> Tag


Purpose The <BGSOUND> tag is used to specify a background sound, or soundtrack, that will play when the page is loaded. Syntax <BGSOUND> Attributes Attribute Required Purpose

SRC

Specifies the source of the sound in the form of a URL, or a file.

Example <BGSOUND SRC="tada.wav">

The <COMMENT> Tag


Purpose The <COMMENT> tag is used to insert remarks, which are not displayed, into an HTML document. Any text that is surrounded by the <COMMENT> tag is not displayed on the screen. The <COMMENT> can also take the one-tag form of: <!--...- ->. Syntax <COMMENT>...</COMMENT> or <!-- ... - -> Attributes None. Example <COMMENT>Version: 3</COMMENT> <!-- This is version 3 - ->

The <HTML> Tag


Purpose The <HTML> tag is used to specify the beginning and end of an HTML document. Everything that is related to HTML (including the <HEAD> and <BODY> should fall in the <HTML> tags). Syntax

<HTML>...</HTML> Attributes None. Example <HTML> <HEAD> <TITLE>This is a test</TITLE> </HEAD> <BODY BGCOLOR="C0C0C0"> <H1> This is a test</H1> </BODY> </HTML>

HTML Terminology
This section defines some general HTML terms and some Internet terminology that can help you read this appendix.
q

q q

Attribute: Usually refers to a property of an HTML tag that the user can change. For example, the HREF property is an attribute of the <A> tag. Encapsulation: Refers to when the start and ending (<TAG> and </TAG>) tags surround text and other tags for rendering, or other purposes. Element: Refers to the tags (such as <EM>). An element may also refer to the key word without the angle brackets (EM instead of <EM>). Entity: An entity, in HTML, is a tag, or a group of tags that have common purpose. The <B> tag renders text as bold, while client side image maps are used for making clickable maps. HTML: This stands for Hypertext Markup Language. Value: A value is what the user can assign an attribute of an HTML tag, if it requires a value. Some attributes do not require a value. The presence of a valueless attribute in a tag indicates some change. URL: This stands for Uniform Resource Locater, which is the standard means for referencing information over the Internet. For example: http://www.microsoft.com/ie/ie.htm is a URL, http:// is the type of resource that is being requested by the URL (in this case its hypertext

transfer protocol). www.microsoft.com is the address (domain name) from where to get this resource and /ie/ie.htm is the location and name of the resoure.

Color Names Supported by Internet Explorer 3.0 Beta 1


This section covers all the colors supported in Internet Explorer 3.0 and their corresponding hexadecimal value in the form of #RRGGBB. RR is the color intensity of red of the color (a hexadecimal number from 0-FF), GG is the color intensity of green of the color (a hexadecimal number from 0-FF), and BB is the blue color intensity of the color (a hexadecimal number from 0FF). Color Name "aliceblue" "antiquewhite" "aqua" "aquamarine" "azure" "beige" "brisque" "black" "blanchedalmond" "blue" "blueviolet" "brown" "burlywood" "cadetblue" "chartreuse" "chocolate" "coral" "cornflowerblue" "cornsilk" "crimson" "cyan" "darkblue" "darkcyan" "darkgoldenrod" Hexadecimal Value "#F0F8FF" "#FAEBD7" "#00FFFF" "#7FFFD4" "#F0FFFF" "#F5F5DC" "#FFE4C4" "#000000" "#FFEBCD" "#0000FF" "#8A2BE2" "#A52A2A" "#DEB887" "#5F9EA0" "#007FFF" "#D2691E" "#FF7F50" "#6495ED" "#FFF8DC" "#DC143C" "#00FFFF" "#00008B" "#008B8B" "#B8860B"

"darkgray" "darkgreen" "darkkahki" "darkmagenta" "darkolivegreen" "darkorange" "darkorchid" "darkred" "darksalmon" "darkseagreen" "darkslateblue" "darkslategray" "darkturquoise" "darkviolet" "deeppink" "deepskyblue" "dimgray" "dodgerblue" "floralwhite" "forestgreen" "fuchsia" "gainsboro" "ghostwhite" "gold" "goldenrod" "gray" "green" "greenyellow" "honeydew" "hotpink" "indianred" "indigo" "ivory" "khaki"

"#A9A9A9" "#006400" "#BDB76B" "#8B008B" "#556B2F" "#FF8C00" "#9932CC" "#8B0000" "#E9967A" "#8FBC8F" "#483D8B" "#2F4F4F" "#00CED1" "#9400D3" "#FF1493" "#00BFFF" "#696969" "#1E90FF" "#FFFAF0" "#228B22" "#FFFF00" "#DCDCDC" "#F8F8FF" "#FFD700" "#DAA520" "#808080" "#008000" "#ADFF2F" "#F0FFF0" "#FF69B4" "#CD5C5C" "#4B0082" "#FFFFF0" "#F0E68C"

"lavender" "lavenderblush" "lawngreen" "lemonchiffon" "lightblue" "lightcoral" "lightcyan" "lightgreen" "lightgrey" "lightpink" "lightsalmon" "lightseagreen" "lightskyblue" "lightslategray" "lightsteelblue" "lightyellow" "lime" "limegreen" "linen" "magenta" "maroon" "mediuaquamarine" "mediumblue" "mediumorchid" "mediumpurple" "mediumseagreen" "mediumslateblue" "mediumspringgreen" "mediumturquoise" "mediumvioletred" "midnightblue" "mintcream" "mistyrose"

"#E6E6FA" "#FFF0F5" "#7CFC00" "#FFFACD" "#ADD8E6" "#F08080" "#E0FFFF" "#90EE90" "#D3D3D3" "#FFB6C1" "#FFA07A" "#20B2AA" "#87CEFA" "#778899" "#B0C4DE" "#FFFFE0" "#0000FF" "#32CD32" "#FAF0E6" "#FF00FF" "#800000" "#66CDAA" "#0000CD" "#BA55D3" "#9370DB" "#3CB371" "#7B68EE" "#00FA9A" "#48D1CC" "#C71585" "#191970" "#F5FFFA" "#FFE4E1"

"lightgoldenrodyellow" "#FAFAD2"

"moccasin" "navajowhite" "navy" "oldlace" "olive" "olivedrab" "orange" "orangered" "orchid" "palegoldernrod" "palegreen" "paleturquoise" "palevioletred" "papayawhip" "peachpuff" "peru" "pink" "plum" "powderblue" "purple" "red" "rosybrown" "royalblue" "saddlebrown" "salmon" "sandybrown" "seagreen" "seashell" "sienna" "silver" "skyblue" "slateblue" "slategray" "snow"

"#FFE4B5" "#FFDEAD" "#000080" "#FDF5E6" "#808000" "#6B8E23" "#FFA500" "#FF4500" "#DA70D6" "#EEE8AA" "#98FB98" "#AFEEEE" "#DB7093" "#FFEFD5" "#FFDAB9" "#CD853F" "#FFC0CB" "#DDA0DD" "#B0E0E6" "#800080" "#FF0000" "#BC8F8F" "#4169E1" "#8B4513" "#FA8072" "#F4A460" "#2E8B57" "#FFF5EE" "#A0522D" "#C0C0C0" "#87CEEB" "#6A5ACD" "#708090" "#FFFAFA"

"springgreen" "steelblue" "tan" "teal" "thistle" "tomato" "turquoise" "violet" "wheat" "white" "whitesmoke" "yellow" "yellowgreen"

"#00FF7F" "#4682B4" "#D2B48C" "#008080" "#D8BFD8" "#FF6347" "#40E0D0" "#EE82EE" "#F5DEB3" "#FFFFFF" "#F5F5F5" "#FFFF00" "#9ACD32"

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

Appendix C - VBScript Coding Conventions

Coding conventions are nothing more than a set of rules pertaining to good programming practice. A computer can understand "spaghetti code" (convoluted, messy code that makes no sense at all to a human who tries to understand it) and other types of gobbledygook that would drive any sane person over the edge. By adhering to some simple guidelines, your code will not only be understandable to the next person who needs to maintain it, but, even you will be able to understand it six months after you wrote it. These guidelines are based on commonly accepted rules of good programming practice, but they are not carved in stone. Pick what you like, modify what you don't like, and create your own set of rules that you can understand and communicate to others should the need arise. But, by all means, once you've determined which set of rules to use, use them, and use them rigorously and consistently.

Controls
When you create a control using a tool such as the VB IDE, or the ActiveX Control Pad, the control is created with a default name, such as Frame1. While any name can be used, it's good practice to replace the default with a more meaningful name. It's also extremely helpful to use a prefix, so you will know what type of control it is when looking at code it pertains to. For example, Frame1 tells you that the object in question is a Frame control, Options gives you a clue about what the control pertains to, and fraOptions lets you know that you're dealing with a Frame control that has something to do with Options. Since the inception of Visual Basic, common usage has resulted in a widely-accepted collection of control name prefixes. If you use these prefixes, there will never be any confusion as to exactly what type of controls you're using. There are literally thousands of ActiveX controls available. Obviously, somewhere along the line, you'll either have to use the same three-letter prefix for two different types of controls, or, apply a longer (or shorter) prefix to distinguish between them. Table C.1 lists some typical prefixes suggested by Microsoft.

Table C.1 Typical ActiveX Control Prefixes Control Type 3D Panel Animated Button CheckBox ComboBox Command Button CommonDialog Frame Image Label Line ListBox Spin TextBox Vertical ScrollBar Slider Prefix pnl ani chk cbo cmd dlg fra img lbl lin lst spn txt vsb sld

Horizontal ScrollBar hsb

Variables and Constants


Like controls, variables should also be given prefixes that identify their type. In addition to documenting a variable's type, you should consider adding an additional prefix to describe its scope if it's not a global variable. Microsoft suggests prefixing a variable name with an s if it's a Script-level variable. Thus, using the suggested prefix from Table C.1 for a Script-level Integer variable, a typical example would be sintUserID. Remember, these prefixes are strictly for the benefit of people (including you, of course) who read the codegiving a String a prefix of "byt" will not change it into a Byte!

Functions (in addition to executing code) return values. Therefore, you should also use these prefixes in your Function declarations.

Table C.2 contains the variable type prefixes Microsoft recommends. Table C.2 Variable Name Prefixes Variable Type Prefix Boolean Byte Date/Time Double Error Integer Long Object Single String bln byt dtm dbl err int lng obj sng str

Procedures
Procedure names, like variable names, should be given descriptive names. Functions, like variables, should be given a type prefix according to the examples in Table C.2, because they return a value; Sub procedures, on the other hand, don't return any value, and therefore require no prefix.

Loops, Blocks, and White Space


Just as judicious use of white space makes text easier to read, a well-formatted code listing is easy to understand at a glance. When loops and other structures are properly indented, it's immediately apparent how the program is intended to flow. It's much easier to debug a program where each nested If/Then is indented a few spaces more than the preceding level. Placing all code flush left may be a little easier when you first type it in, but doing so guarantees you a maintenance nightmare. If you simply indent each level of a loop and block by three or four spaces, you'll do well. Here's how some typical code should look: Sub CheckOrder For intC = intStart to intFinish

If intRequired(intC) <= intOnHand Then Select Case intOnHand Case intReorderLevel GeneratePO ProcessOrder Case Is < intReorderLevel ProcessOrder End Select Else NotifyReceiving EndIf Next End Sub Compare the preceding section of code with the following, and see which you would rather work with: Sub CheckOrder For intC = intStart to intFinish If intRequired(intC) <= intOnHand Then Select Case intOnHand Case intReorderLevel GeneratePO ProcessOrder

Case Is < intReorderLevel ProcessOrder End Select Else NotifyReceiving EndIf Next End Sub In addition to using white space for indentation within a block of code, major sections of code (i.e., scripts, and major sections within scripts)should also have a blank line between them, to visually separate them.

Comments
It's important to comment every significant thing your program does and contains. Put blocks of indented comments at the start of every procedure (and every major section within a procedure), describing the purpose of the code that follows and providing meaningful information about how it accomplishes its task. Describe which variables it uses, which ones it modifies, and which it returns. You should also place in-line comments at the end of significant lines of code, explaining what's being done.

HTML Considerations
As this book goes to press, recommended placement for scripts within HTML pages is uncertain. Some sources within Microsoft suggest placing them within the <HEAD> section, and others recommend putting them at the end of the <BODY> section. This is largely a style consideration, inasmuch as execution is unaffected by placement. Regardless of where you put them, you should consider surrounding your scripts in HTML Comment tags (<!--...-->) to prevent them from appearing as text when viewed by non-ActiveX-enabled browsers. Also, even though they won't actually do anything in browsers that don't support ActiveX, HTML controls will be visible in them if you place them within <FORM> blocks.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

- Special Edition Using Visual Basic Script -

Appendix D - Porting Visual Basic Applications

When VBScript first appeared on the scene, it seemed unlikely that any effort to port VB programs to VBS scripts was even remotely feasible. Even apart from language limitations (such as no file I/O, no Typed structures, no Class modules, no Collections, and so on), the overriding reality was that VBS "applications" were HTML-bound. As has oft been noted, HTML, basically an upper-left to lowerright text-flow formatter, is ill-suited in situations that vector off from its original mission. The recent appearance of HTML Layout Page functionality, combined with the productivityenhancing ActiveX Control Pad have changed this assessment to the degree that it is no longer unthinkable to port some VB applications to the Web. If you are willing to do a fair amount of work dealing with the limitations and differences that remain, you will be able to bring certain VB applications to VBScript. At the very least, you should be able to duplicate most, if not all, of your user interface elements. Even so, there are some showstoppers you need to be aware of from the start. If your program depends on any of them, you'll need to seriously consider whether you want to proceed.

Considering a Few Caveats


HTML Layout Pages, for all their similarity to VB Forms, are severely lacking in terms of properties, methods, events, and behavior. Essentially, they are dumb containers of controls; if you need to do anything at the form level (VB form, not HTML form), it won't happen, at least at this stage of the game. This includes such things as using the Print method to place text directly on a form, graphics methods (Line, Circle, and so on) to draw on a form, hiding, showing, or unloading a form, and trapping any events (such as mouse clicks or keystrokes). You won't be able to do anything with Typed records. You may be able to get around this limitation by using multi-dimensional arrays, or, groups of arrays. You can't create Collections. Again, you may be able to use arraysthis was SOP prior to VB4, so it's definitely within the realm of "doability." Class modules don't exist in VBScript. Nor, for that matter, do standard .BAS modules. You can deal with the latter omission by placing your procedures in the same file as your controls, or the HTML

file that holds points to it. (At the time this book goes to press, HTML Layout Pages must reside in . ALX files, and an <OBJECT...> reference to the .ALX file must be placed in an HTML file. Microsoft has announced that when IE 3.0 is released, it is expected to support the use of HTML Layout Pages within an .HTM page.) As to Class modules, you may be able to duplicate their functionality by using procedures. Clearly, if you have a heavy investment in Class modules that you want to port over to Web applications, it may be in your interest to wait a while. See "Sweeping the Horizon," in this appendix for what may be a glimmer of hope. Other features that you're "protected" from include the Printer Object, communications ports, and API (or other .DLL) calls. File I/O is a real problem. You can write Class wrappers in VB4, and compile them to in-process . DLLs (for information on this topic, check out Que's "Special Edition Using VB4"), but, you should realize that it's an exercise that's not for the faint of heart. In addition to heavy VB coding, you'll need to embed <OBJECT> tags at the HTML level, using ClassID references, and at this time, it's impossible to use them with HTML Layout Pages, as the ActiveX Control Pad won't work with anything that doesn't meet the new ActiveX qualifications. If you get that far, you'll still be faced with a security issue. The creators of the Internet Explorer have not simply relied on VBScript's lack of native file I/O for protection from malicious programmers. Attempting to use an object that does not contain a valid digital signature from a certificate agency, will result in warning boxes being displayed each time the page is loaded, unless security in the Internet Explorer is shut down. Shutting down security is definitely not recommended unless you are absolutely certain that the browsers in question will never wander off the safety of a corporate Intranet.

Sweeping the Horizon


If you do require language and/or object functionality that is not available in VBScript, you should remember that VBScript, VB, Internet Explorer, Windows, and even the Internet, are all moving targets. The only time something stands still is when it's dead in the water. It's not unreasonable to hope that later versions of the platform will include functionality that is missing now. Right now, VBScript is in its first generation. Windows is poised to undergo a major transformation, as the desktop blends into the Internet. No one outside the inner sanctums at Microsoft can say exactly where things will end up, although we do know that in general, we'll be getting better tools, more robust language implementations, and easier means for accomplishing tasks. Microsoft has been dropping teasers in the press regarding the next major release of Visual Basic. Some of what they've publicly made known has a direct bearing on the things you'll be doing with VBScript and HTML Layout Pages. For instance, you'll be able to write your own ActiveX controls, and roll in whatever functionality you require. Because Visual Basic is a full-featured language, this means that you should be able to supply much of the functionality that is currently missing from VBScript.

In the majority of cases, if you have a VB application that you want to port to VBS, you'll be looking at a complete rewrite. You should, however, be able to preserve the "look and feel" of your applications, assuming you can avoid use of graphics methods and form events. Many specific procedures, and much of your existing event code routines, can be carried over to VBScript, in some cases with little or no change. However, the structural aspects of your codeModules, Classes, and data structureswill need to be redesigned, or rewritten. If, after you assess the situation, you realize that the law of diminishing returns has been invoked, you'll need to make the hard choice to either scrap the project, or come up with a workable alternative. No amount of advice or counsel can protect you from situations like this, and although they test your mettle, they can also provide opportunity. Take the resources at hand, reason out the situation, and present a solution. That's what sets you apart from the pack.

| Previous Chapter | Next Chapter | | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Introduction

Part I - JScript: The Language


q q q q

Chapter 1 - What Is JScript? Chapter 2 - JScript: The Language Chapter 3 - Events and JScript Chapter 4 - JScript Objects

Part II - JScript Objects


q q q q q

Chapter 5 - Built-In JScript Objects Chapter 6 - Interactive HTML Objects Chapter 7 - Advanced HTML Objects and Navigation Chapter 8 - Dynamic HTML and IE Objects Chapter 9 - Creating Your Own JScript Objects

Part III - Live Content and JScript


q q q q

Chapter 10 - A Java Tutorial Chapter 11 - More About Java Chapter 12 - Scripting and ActiveX Chapter 13 - More About ActiveX

Part IV - Advanced JScript


q q

Chapter 14 - Controlling Web Page Appearance Chapter 15 - Visual Effects

q q q q

Chapter 16 - Creative User Interaction Chapter 17 - Using Frames and Cookies Chapter 18 - Development Tools for JScript and Live Content Chapter 19 - The ActiveX Control Pad

Part V - Appendixes
q q q

Appendix A - JScript and ActiveX Resources Appendix B - JScript Glossary Appendix C - JScript Commands and Grammar

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Chapter 1 What Is JScript?


q

What Is JScript? r Live Content on the World Wide Web s Forms Explode with Information s Listing1.1 JSPUNCH.HTM--Code for JScript Punchline s Look and Feel Is an Option s Listing1.2 HANALYSI.HTM--Frames for HTML Analysis s Listing 1.3 HANALYS1.HTM--Code for HTML Analysis s Multiple Windows and Frames s Interacting with Other Live Objects r The Role of Scripting s Macros Become Scripts s Scripting in Macintosh Applications s Perl Started as a UNIX Scripting Language r JScript Extends the Capabilities of the HTML Page s JScript Pages Work Differently from Standard HTML Pages s JScript Meets the HTML Page s JScript Can Access Browser Objects r JScript and Java s JScript and Java Work in the Same Environment s JScript Is NOT Java s Java and JScript Working Together s JScript and Other Live Content Tools

What Is JScript?
In this chapter, you will learn
q q q q

JScript on the Web See how simple JScript pages can be JScript pages can also be complex Learn the difference between JScript and Java

Scripts make great applications Remember the thrill of creating your first Web page and clicking your first hyperlink to another site? The excitement of surfing from California to Maine, from

Australia to Finland? This interactive nature of the Web attracts millions of people to the Web every day. With JScript, new dynamic elements let you go beyond the simple click-and-wait. Users will not just read your pages but also interact with them. Your pages come alive for any user, even with the slowest Internet connection. Users will get quick responses, because the interaction does not need to involve the server but can take place in the user's browser. This interaction can change your pages into an application. Put together a few buttons, a text box, and some code to produce a calculator. Or an editor. Or a game. Or the "killer" JScript application that everyone wants. Users will save your JScript-enhanced pages to use your application again and again. We saved a Web page with a JScript calculator so we could have a calculator handy. We also have an HTML editor written in JScript saved on our hard drives. JScript is a programming language that allows scripting of events, objects, and actions to create Internet applications. This chapter will introduce you to JScript and teach you the following:
q q q q q

Examples of live content on the World Wide Web The role of scripting languages JScript as a scripting language JScript is different from Java Where you'll find JScript

Live Content on the World Wide Web


In building Web pages, you present information to your audience. The design and layout should entice them to explore your site. Your hyperlinks provide several predefined but different paths to see your information. With JScript, your pages come alive! Your pages respond to the requests of your audience beyond a simple click here or there. Many more interactive elements ar[infinity][radical]now available for exciting design and layout. Your users are no longer just readers. People will interact with your documents, not just read them. Your users can now interact with forms, change the look and feel of your Web documents, and use multiple windows.

Forms Explode with Information


With JScript, forms are a consideration in nearly every page you design. Text fields and text areas can dynamically change in response to user responses. Your audience will look for buttons, selections, option buttons, and check boxes. Your pages will change at their touch. The following examples show you how JScript makes forms come alive:
q

Calculators--Where is that calculator when you need it? It's on your page (see Figure 1.1). Beyond simple arithmetic, you can do conversions in hexadecimal, calories, metric, and more.

Expand the form and you have the unlimited world of spreadsheets. For example, simple tax forms, grade-point averages, and survey analysis. Figure 1.1 This Web page has a calculator built in with JScript.
q

Display the time--What time is it? It's easy to show in a basic text box (see Figure 1.2). Or how about the time anywhere in the world? Add in a little math, and show users the elapsed time. Different math produces a countdown time. A little different code, and you have a population explosion or national debt counter.

Figure 1.2 JScript time displays can show you the local time in any time zone.
q

Feedback status--As you build JScript applications, there will be a lot going on. Your code will have loops and increment variables, and will track user inputs. Let the users in on what's going on--Provide feedback with a numeric counter (see Figure 1.3). Say it "graphically" with a bar graph made of ASCII characters, and show a status literally.

Figure 1.3 Text boxes can show feedback status of applications to users numerically, with ASCII graphics, or verbally, in text boxes.
q

Verification--With user input, you usually want to verify the validity of the response. For example, if you want the response to be a number between 1 and 10, JScript can verify that the user's response falls in that range. If not, the code can notify the user and ask again for the input (see Figure 1.4). Once verified, the result is submitted to the server.

Figure 1.4 Provide your users with instant feedback without waiting for a response from the server.
q

Entertainment--Everyone wants to have fun--even when learning. You can convey your information as an interactive game or even as a joke (see Figures 1.5 and Figure 1.6). The source code is very simple. It is given in Listing 1.1, and is on the CD-ROM as the file JSPUNCH.HTM.

Figure 1.5 Punchline: Now you see the joke without the punchline revealed. Figure 1.6 Here's the punchline, hidden until you are ready to see it. The source code in Listing 1.1 is easy to modify for you to tell your own jokes on the Web without

giving away the punchline.

Listing 1.1 JSPUNCH.HTM--Code for JScript Punchline


<HTML><HEAD><TITLE>JScript Punchline demo by Ray Daly</TITLE> <SCRIPT LANGUAGE="JavaScript"> <!--hide this script from some browsers function Punchline () { document.open(); document.write ("<BODY BGcolor=#00EE00><P><I>To get to the other side.</P> </I>") ; document.close(); } // hidden ray.daly@mailcall.com 12/16/95--> </SCRIPT> </HEAD> <BODY> <H1>Punchline</H1> <H2>A jJScript Punchline demo by Ray Daly</H2> <P>Why did the chicken cross the road?</P> <FORM> <P><INPUT TYPE="button" VALUE="Punchline" onClick="Punchline()"> </P></FORM></BODY></HTML>

Look and Feel Is an Option


All of the elements inside the window of a browser are available in JScript. You can dynamically change some of these elements, or you can examine the elements of one document and use that information to create a different document. Here are some examples of changing the look and feel of documents.
q

Change colors--Ever get to a page where the colors nearly make you go blind? Give your users a choice of several color combinations of backgrounds and text colors. As your application displays documents, use your users' colors.

TIP: There are too many colors for users to choose from. Don't make them experiment; let them select some good combinations you have already tested.

Change links--Normally, users click hyperlinks and off they go to the site you specified as the URL for this hyperlink. With JScript, this link can change, based on user responses. If a user indicates a preference for baseball over football, your code can change the hyperlink to point

to the Yankees instead of the Cowboys.


q

Reformat pages--Since JScript can examine all of the elements of a document, you can read a document in one frame and completely reformat it in another. An example is HTML Analysis (see Figure 1.7). In the control panel at the bottom of the window, you specify an URL that is displayed in the left frame. The right panel is generated from the code activated by the REDO button. This code reads the HTML code of the left document and creates an entirely new document that lists all of the hyperlinks. This new document is displayed in the right frame.

Listing 1.2 shows the frames for the top level frame for HTML Analysis. It uses three files, HANALYSI.HTM, GUIDE.HTM, and HANALYS1.HTM, all of which are on the CD-ROM.

Listing 1.2 HANALYSI.HTM--Frames for HTML Analysis


<HTML><HEAD><TITLE>HTML Analysis by Ray Daly</TITLE></HEAD> <FRAMESET ROWS="80,300,*"> <FRAME SRC="hanalys1.htm" NAME="control"> <FRAME SRC="" NAME="displayhere"> <FRAME SRC="" NAME="analysis"> <FRAME SRC="guide.htm" NAME="guide"> </FRAMESET></HTML> Listing 1.3 shows the code for the HTML Analysis itself.

Listing 1.3 HANALYS1.HTM--Code for HTML Analysis


<HTML><HEAD><TITLE>hanalys1.htm: part of hanalysi.htm</TITLE> <SCRIPT Lanuguage="JavaScript"> function doit() { for (i = 0; i <parent.displayhere.document.links.length; i++) { parent.analysis.document.write (parent.displayhere.document.links [i] + "<BR>") } }</SCRIPT></HEAD> <BODY> <A HREF="http://www.cris.com/~raydaly/htmljive.html" TARGET="displayhere"> Get a page.</A> <FORM><INPUT TYPE="button" VALUE="Probe it" onClick="doit()"></FORM> </BODY></HTML>

CAUTION: The HTML Analysis application is not stable on all platforms. Make sure the URL is completely loaded before you do the analysis.

TIP: You can reformat pages for dramatic results. Instead of showing the entire document in a large frame, bring the source document into an extremely small frame. Then, display your reformatted document in the much larger frame. If the frame with your source is small enough, your users won't even know what the original looked like.

Analyzing tools--Analyzing tools are a very interesting derivative of reformatting documents. Instead of displaying a reformatted document, analyzing tools provide an analysis of a document. Tools could check such simple things as word counts, link counts, or other statistics. Code could even be written to show the tree structure of all of the objects in a document. Or you could write code to verify that pages meet the criteria for your corporate site.

Figure 1.7 The URL specified in the top frame is displayed in the second frame. The third frame shows only the links from that page. Such tools are a great way to make certain pages on your site meet your standards.

Multiple Windows and Frames


Netscape introduced frames and LiveScript with Navigator 2.0. Since then, LiveScript has evolved considerably. As a result of its convergence of features with the Java programming language, it was renamed to "JavaScript." Internet Explorer (IE) also supports JavaScript, now, through Microsoft's implementation of "JScript." Since their introduction, both JavaScript and JScript have grown explosively and are used in many Web sites. One of its most popular features is the ability to open multiple windows for browsing the Web. Add some JScript behind these new features, and the browser becomes a kaleidoscope on the World Wide Web. No longer are you limited to browsing one page at a time. Now you can view multiple documents and see a multifaceted view of the Internet world. The following list examines the use of multiple windows and frames:
q

Alert, confirm, and prompt dialog boxes--JScript has its own built-in windows that you can use in your design. Alert users to take caution (see Figure 1.8), confirm an action with an okay or cancel response (see Figure 1.9), or prompt for a text input (see Figure 1.10).

Figure 1.8 An Alert box notifies the user but provides no choices. Figure 1.9

A Confirm box notifies users and allows them to cancel the action. Figure 1.10 A Prompt box lets the user type a response to your code.
q

Control windows--You can create your own controls with custom windows. Populate them with buttons, text boxes, or icons to control the results in your other windows. Navigation windows--Have two, three, or more windows all opened simultaneously. As the user navigates from one, the others display various screens of information. For example, each window might pull in a live image from a different point around the globe, as selected by the user. Internet Tri-Eye (see Figure 1.11) provides live views from around the world.

Figure 1.11 Internet Tri-Eye is an example of a multiwindow application and a control panel. Selections in one frame produce results in other frames.

Interacting with Other Live Objects


Sun Microsystems and Netscape Communications introduced JavaScript. An additional 28 leading computer companies, including Microsoft, AOL, AT&T, Borland, Digital Equipment Corporation, Hewlett-Packard Corporation, and Oracle Corporation have endorsed the JavaScript or its JScript implementation. These companies support JScript because it is an open-standard object language. Several companies will introduce products that incorporate JScript. This will allow even more interaction. Internet Explorer 3.0 supports a new functionality-enhancing feature that provides inline support for a huge range of Live Objects, known as ActiveX controls. With Live Objects, developers can deliver rich multimedia content through Internet sites, allowing users seamlessly to view that content with ActiveX controls, which will perform a wide variety of tasks without launching any external helper applications.

The Role of Scripting


There is no definitive definition of a scripting language. Sometimes the term is used to make a distinction from compiled languages such as C or C++. The term scripting is also used because a language will react to, control, or "script" a series of events. Even macro languages built into applications such as spreadsheets, databases, word processors, and multimedia applications are now often called scripting languages. The purpose of most scripting languages is to extend the capability of an application. Just as the author of this book cannot imagine every creative use you will make of JScript, software authors cannot imagine every possible use of their applications. To make their products more versatile, they add a scripting language. With JScript, you have a scripting language to use your imagination on the

Web. Current uses of scripting languages may give you an insight into the potential of JScript. You probably know that macros are built into many applications. Apple's HyperCard contains a very powerful scripting feature. Perl is a scripting language used in many CGI scripts on the Web.

Macros Become Scripts


Traditionally, a macro feature was added to application software to allow a simple series of commands to be executed with a single keystroke. With great fanfare, publishers introduced this feature as a way to reduce repetitive tasks and save time. For example, a word processor's simple macro might change the entire style of a document. Over time, the macro feature of various applications became complex scripting languages. As scripts became longer and nontrivial, they extended the software beyond its normal purpose. New and creative combinations of commands made the software the basis for entirely new applications--for example, a set of word processing scripts for maintaining a small mailing list. These scripting languages in software are so sophisticated that they are the subject of college courses. Many universities now require courses in spreadsheet scripting for accounting and business students, art majors are learning scripting procedures for high-end graphics and multimedia packages, legal courses include using scripts to create documents, and computer science majors have a variety of courses involving scripting languages. A defining factor of these types of scripting languages is that they work only with applications. Scripts in word processors add word processing features. Scripts in spreadsheets add spreadsheet features. These scripts do not go beyond the nature of the software, but they use the existing commands of that software. In our example, the mailing list script still works with words, the standard element of the word processor. This becomes a limitation on the usefulness of this script. With the popularity of program suites such as Microsoft Office, Lotus SmartSuite, and Perfect Office, software publishers have started making the same scripting language work with more than one application. Not only is the same language used in each application, but the scripting language helps the applications work together. Microsoft expanded the role of Visual Basic to work with Microsoft Access and Excel. Lotus has developed LiveBasic for its product suite. The same logic, when applied to the World Wide Web, led to the development of JScript. Historically, scripting has made several "killer applications." These are applications that define a whole new category of software, significantly expand the market, and provide a primary reason for people to use a computer. The first successful spreadsheet was VisiCalc, which mostly disappeared with the success of Lotus 1-2-3--the latter had scripting. There were many different database applications on the market before Ashton-Tate's dBase, but this product was programmable with a scripting language. Scripting gave these applications a great feature that people wanted. Perhaps more important were the

actual scripts people created to extend the capabilities of these products. The existing scripts became an investment in these products that prevented users from switching to competitive products, even if they had more features. Scripting gave these applications a competitive edge. First, it was a feature that could be used to sell the product. Second, people actually started to use the feature and create significant new capabilities for these products. Third, these scripts create a whole new market with magazine articles, books, third-party software publishers, and training. Fourth, the continuing use of these scripts became an investment in these products by the user: Existing scripts often prevented users from switching to competitive products. And finally, even when a competitive product was introduced with new features, someone would introduce scripts that attempted to add these features into the existing products. Scripts allowed both publishers and users to advance.

Scripting in Macintosh Applications


The most notable use of scripting on the Macintosh is Apple's HyperCard program. This application lets you build a group of cards and hyperlink them together. The cards could contain not only text but multimedia files. The stack of cards that you construct could respond to user input. The scripting language is such a strong element of HyperCard that many people consider HyperCard itself to be a language. Many Mac owners were initially disappointed with HTML because it lacked many of the abilities of HyperCard. In many ways, JScript brings some of the HyperCard features to the Web.

Perl Started as a UNIX Scripting Language


If you have used the Web, you have used Perl. It is the language used for the majority of CGI scripts. These are routines that run on Internet servers and respond to requests from browsers when a user completes a form. There are guestbooks, message boards, voting pages, surveys, and more that use Perl scripts. Perl is an interpreted language. While you should be able to find a version of Perl for almost any computer platform, it was created for UNIX systems. It is now platform- independent. The vast majority of Perl scripts will run without modification on any system. Take a script written on UNIX, and it will run perfectly well on DOS. CGI scripts are a type of script that responds to events. In this case, the event is a user submitting data from an HTML form. The attributes of a <FORM> include ACTION, which defines the script to process the data when it is submitted. For example: <FORM ACTION="\cgi-bin\guestbook.pl"> will process the data from the form in a script called guestbook.pl. More than likely, this routine would store the data in a file and return an HTML page to the browser as feedback. It would probably

say something like, "Thanks for your entry into our guestbook." Perl is freely distributed on the Internet, but please see its license for more detail. You should be able to find a version for your system using any of the Internet search services. Larry Wall created and maintains it. Perl's strength as a language is in manipulating files and text to produce reports. This capability, along with its associative arrays, makes it a natural fit for creating CGI scripts. In a few lines, you can process data and return an HTML document in response to an HTML form. If you are a Perl programmer, you can rather quickly learn JScript. Both have a similar control structure and both are interpreted languages. Unlike Perl, JScript is object-based, but it is not nearly as complex. You might miss the text-processing capabilities of Perl, but you will find JScript a delightful new language to learn. There are some cases where JScript is not the appropriate solution, but using Perl for a CGI script would fit the requirement. Generally, if you need to store information, you are going to have to do that on the server, and Perl would be a good choice.

JScript Extends the Capabilities of the HTML Page


Like other scripting languages that extend the capabilities of the application with which they work, JScript extends the standard Web page beyond its normal use. You have already seen in this chapter numerous ways to make your Web site come alive. Given the flexibility of the language, the only limit is your imagination. We must now consider how JScript works within HTML pages.

JScript Pages Work Differently from Standard HTML Pages


With the standard Web site, you get more information by clicking a hypertext link, and the server sends you another file. On a more interactive page, you complete a form, submit the results to the server, and wait for a response. In either case, you must wait for the server to send a new file. This information is almost always a new page, though it might be a multimedia file such as an audio clip or an animation. With JScript-enhanced pages, there is JScript code embedded in the HTML code. The JScript can instantly provide you with information without waiting for the server or your Internet connection (see Figure 1.12). This information can come from user input, code "hidden" within the document, or other documents in frames or other windows. A JScript-enhanced page makes this new information visible by updating the contents of a form or by generating an entirely new document. In a JScript calculator (as seen earlier, in Figure 1.1), the form is updated when numbers are entered. In "Punchline" (refer to Figure 1.5), the user clicks the button, and a new document is created from the "hidden" punchline of the joke.

Figure 1.12 With standard HTML pages, a Web site serves each page to the browser. With JScript-enhanced pages, the source for a page can be the existing page.

JScript Meets the HTML Page


JScript works with browsers by embedding code directly into an HTML page. A new generic tag called <SCRIPT> has been added to HTML to recognize scripting languages. To inform the browser that your code is JScript, you must add the attribute of LANGUAGE="JavaScript" to the <SCRIPT> tag. Much of your JScript coding is enclosed within these tags, as you can see in the following example: <SCRIPT LANGUAGE="JavaScript"> a = "Hello!" //...set a variable called `a' to a value of "Hello!" </SCRIPT> Like most any other computer language, JScript allows you to place comments within your code. Single-line and multiple-line comments are possible. A multiple line starts with the following two characters: /* It ends with the two characters: */ Consider the following example: /* This is the start of multiple lines of comments. This is the end */ To make a comment at the end of a line or on a single line, just use the characters // and everything after that until the end of the line will be considered a comment. Between <SCRIPT> tags, you can write two types of code: direct statements and functions. Direct statements are executed by the browser as they are loaded. For example, objects are initialized in direct statements. Functions are blocks of code that are executed only by other code or events. See Chapter 3, "Events and JScript," for more information about code and events, p. 59 For example, mouse-click events usually trigger functions. Most of your programs will use both direct statements and functions. Many existing HTML tags now have additional attributes to support JScript. For example, all elements of a form can now be identified with the NAME element. You should be familiar with the NAME attribute because it has long been used in creating anchors. Using NAME to identify objects in your documents will generally simplify your coding and debugging.

Another addition to HTML is the ability to recognize events such as mouse clicks, changes in text boxes, and the loading or unloading of pages. This is how the document recognizes the user interaction. These events are used to trigger JScript actions. The code can be quite straightforward, as in the following: <FORM> <P>Click inside the box and then out to see change. <INPUT TYPE="text" NAME="sample" onChange = "sample.value = a" > <!-- ...after any change in this text box, put the value of a in the box --> </FORM> The JScript code that is triggered by an event can be simple or complex. With simple actions, the entire code can be placed in the event element. This is shown in the previous example with sample. value = a. Throughout this book, you will see more typical examples of where a function is called by the event.

JScript Can Access Browser Objects


Like any language, JScript performs operations. These operations, or methods, manipulate information about objects. In addition to built-in objects such as the String, Math, and Date objects, JScript can also operate on browser objects. This allows you to create new documents and modify your existing forms. JScript works with browser objects in the same way that it manipulates user objects or built-in objects, which makes the language easier to learn. Most of the code manipulates HTML elements that you already know. For example, it will read properties of a LINK or write information into a TEXTAREA. Use elements you already know about to make pages come alive. With Microsoft's ActiveX technology, it is also possible to have JScript manipulate live objects. These operations can give you multimedia capability, such as sound or graphics, for example. Additional features can also be added by extending the capability of the browser with plug-ins or Java applets. These external entities can also be made to interact with JScript.

CAUTION: Plug-ins are written by software publishers to add capabilities to the browser. These publishers are not required to make these plug-ins work with JScript. So, you must look at the specifications of a plug-in to see whether it supports JScript.

JScript and Java

Java and JScript are alike in more than just name. However, there are significant differences between these two languages. As you learn to understand the differences, you will also understand how they can work together. Each has its place and neither does it all. Table 1.1 provides a quick overview of the differences. See Chapter 10, "A Java Tutorial," for more information about Java. Table 1.1 Comparing JScript and Java JScript Interpreted by client Code integrated in HTML documents Loose typing of data types Dynamic binding Script limited to browser functions Works with HTML elements Java Compiled by the author, run on client Applets distinct from HTML document Strong typing of data types Static binding Stand-alone applications Goes beyond HTML (for example, multimedia)

Access browser objects and functionality Limited access to browser objects or functionality

JScript and Java Work in the Same Environment


Both JScript and Java are languages for building Internet applications. These applications require browsers. The browsers run these applications by reading code embedded in an HTML page. In other words, they both work in the same environment. Microsoft, Sun, and Netscape have mounted a high-profile campaign to ensure the security of these products. Neither product writes to the user's hard drive. Sensitive information about the user is also unavailable to these languages. So, both products are limited by security and privacy concerns of their environment. Because the two products have a similar name and work in the same environment, many people do not realize the distinction between JScript and Java.

JScript Is NOT Java


In addition, it appears that more Internet browsers will support Java than JScript, though this is not certain. They display information differently in a browser window. Java applications can stand alone. One is compiled, the other is interpreted. The development tools are different, and they have a surprisingly different audience. Java Displays Are Limited to a Graphic Area. To display information on a Web page, Java is limited to painting its text and graphics within a defined area. Just as images on a page are drawn

within a defined area of the page, so, too, with Java programs. Within these areas, the Java applets can create animations, paint, and use various fonts. However, an applet cannot affect anything outside its area. JScript gives you access to the entire Web page. You can modify properties of the page or any element of the page. You can create new documents or update parts of a form. Unlike Java, JScript lets you change the appearance of any part of your Web documents, not just a limited area. NOTE: The hype on Java is that it is flexible enough to do anything, but currently, it cannot affect anything in a Web page outside the area to which it is assigned. If you want your HTML document to interact with Java, forget it. The only way for Java to control everything on the screen is to write a program from scratch and re-create the entire screen. You basically have to rewrite some browser functions. Directly related to this is Sun's work on a new version of Hot Java, its Web browser. Apparently, the new version's primary goal is to make available general-purpose browser routines for Java programmers. It is not clear at this time how this will play out, but the development of Hot Java is worth watching.

Java Applications Can Stand Alone. Java is a general-purpose language that can create standalone applications. Unlike the Java applets that run in Web pages, these applications may not even connect to the Internet, but may perform business functions such as accounting. This is an important aspect of Java that has many people excited. JScript, like most other scripting languages, works only within an application. Currently, it works with Microsoft's Internet Explorer and Netscape's Navigator browsers and the LiveWire server environment. But JScript applications will not function independently.

CAUTION: Hot Java (not to be confused with Java or JScript) is Sun's own Web browser written in Java. It has shown that Java applications could stand alone. This browser's purpose was to demonstrate the early applets written with the alpha version of Java. With the official release of Java version 1, the original Hot Java is no longer a viable browser. It will not run applets written in Java version 1. A new version of Hot Java is apparently in the works which will support both Java 1.0 applets and JScript.

Java Is a Compiled Language. With Java, you write your code, compile it, and then run it. The person using your Java applet from a Web page cannot look at the source code. For many programmers, there is a sense of security here that you are not giving away your code. JScript is interpreted. The code you write in JScript is the code that the browser executes. There is no intermediate step of creating executable code from the source code. People can look at the source code of the HTML page and read your JScript code and your comments. JScript and Java Development Tools. The first generation of development tools for these

languages has only recently been introduced. Since JScript and Java are very new languages, this is not surprising. However, looking at the nature of the products, some general distinctions between the development tools can be made. Java is very much like the C++ language. It is object-oriented, uses many of the same statements, uses libraries, and is compiled. Several companies that have strong C+ + programming environments are developing similar environments for Java. This will allow the development of large-scale Java applications, but you will have to learn these programming environments. See Chapter 18, "Development Tools for JScript and Live Content," for more information. JScript is tied to the HTML page. The code is embedded in it and it operates on HTML elements. Since the code is interpreted by a browser, the next generation of HTML editors will undoubtedly add features for creating JScript code. JScript and Java Have Different Audiences. Some significant features of Java require a multitasking operating system. So, anyone operating on a UNIX platform, OS/2, Windows NT, and Windows 95 will be able to run Java applications and applets. This is a substantial part of the Internet audience. JScript works in any version of Internet Explorer or Netscape Navigator on any platform it supports. Obviously, this is also a substantial part of the Internet audience. There are some big differences between these audiences. Because JScript is an interpreted language, there is a huge audience of potential JScript authors. All it takes to write a JScript program is a JScript-compatible browser and a text editor. Most HTML editors can also be used to write JScript code. So, millions of people now have all the tools they need to create JScript applications. In a matter of a few months, Microsoft and Netscape have been able to distribute millions of JScript and JavaScript interpreters. It took Microsoft years to distribute nearly as many copies of Microsoft Basic. Learning JScript is easy. By typing in just a few lines, you can be running a JScript application. As you read through this book, you will quickly be incorporating many scripts into your pages. But just as nearly anyone can plant a seed, it does take some patience and skill to create a garden.

Java and JScript Working Together


One of the more important aspects of the interplay between JScript and Java is the commitment to making the languages work together. They share a similar syntax and control structure that make it easier to write code for either language. But more importantly, a JScript page will be able to communicate with a Java applet referenced by the page. Another aspect of this sharing takes place not in the browser, but in the server. Both Microsoft and Netscape have server environments that support scripting, so the scripting language that works on the browser will also work on the server. Just as interactive scripts currently run as CGI scripts, JScript can handle such interaction on newer servers that support it.

JScript and Other Live Content Tools


JScript will be incorporated into more Internet tools. While Netscape introduced JavaScript with

Navigator 2.0, Microsoft has made it an open, cross-platform scripting language which they call "JScript." This means that any publisher can use it as his or her scripting language. This is the primary reason why JScript is gaining wide acceptance. Several companies are expected either to incorporate JScript into their products or to provide an interface to JScript. The most visible products will be the ActiveX controls and plug-ins as discussed previously. Work is also underway to provide other features, such as accessing high-end databases on the server. It will be interesting to see how this market develops. All of this holds great potential for creating an exciting Web experience for your viewers. You will be able to use the same language to enhance your Web page, customize your server, create stunning effects with your controls and plug-ins, and communicate with specialized Java applets. JScript can make your Web page come alive; it can make your site an unforgettable experience that your users will want at the top of their favorites list.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Chapter 3 Events and JScript


q q

Chapter 3 Events and JScript r Events and Actions s Navigation Actions and Events s Forms Input and Events s Actions that Are Not Events r JScript Code in HTML s The SCRIPT Tag s Listing3.1 A JScript <SCRIPT> with a Single Function s Listing 3.2 ex32.htm--An Illustration of Dynamic Binding s Declaring JScript Event Handlers s Listing 3.3ex33.htm--A JScript Function Can Be Shared by Several Event Handlers r Using JScript Event Handlers s Document Level Event Handlers s Listing 3.4ex34.htm--Using the mouseOver Event to Mediate Access s Submit Event Handlers in the FORM Tag s Listing 3.5ex35.htm--Form Content Can Be Validated Using an onSubmit Handler s Event Handlers in <FORM> Elements s Listing 3.6ex36.htm--Values of Different Form Elements Can Be Accessed in JScript s Listing 3.7ex37.htm--An Example of JScripts Text Events

Events and JScript


q q q

Use the HTML SCRIPT tag Attach Event Handlers to HTML elements Intercept button clicks, text entry, and form submission

Accept user input, validate it, and provide feedback Although HTML pages can be difficult to develop, they are usually very simple to use. The number of things you can do with an HTML page is quite limited. For the most part, you simply look at it--read its text, admire its graphics, and, perhaps, listen to the sounds it can play. For many, the Web experience consists of visiting a series of pages

without interacting with them. The only interaction occurs when the user selects a link or clicks an imagemap. HTML forms have gradually changed that model to increase the level of interaction. A form can have a variety of ways of accepting input, including text fields, buttons, check boxes, and multiple choice selections. In this way, HTML forms are a lot like paper forms. The user fills in the form, perhaps to purchase some item, and then submits the form. This submission process also mimics real life. It is difficult to tell whether the form has been properly filled in, and the time taken for processing the form is often quite lengthy. In the case of HTML, this processing delay occurs because the contents of the form must be sent across the network to some URL, processed there, and then returned to the user. Even the slightest error causes the form to be rejected, so that the form entry must be repeated. One of the primary goals of JScript is to localize most of this process and perform the form validation within the user's browser. It won't be possible actually to submit an order locally, but it will be possible to make sure that the form is properly filled out locally, and thereby avoid forcing the user to redo the form. JScript realizes this goal through event handlers. Event handlers are JScript statements (usually functions) that are called whenever something happens. JScript functions can be called when a form is submitted, or they can be called whenever the user does anything to the form. If your form requires that a certain field correspond to a number between 2 and 10, for example, you can write a JScript function that will validate that field when the user changes it, and complain if the value is out of range. This chapter describes event handling in JScript. We discuss all the events that can be handled, as well as the contexts in which these events may arise. In addition, you learn how JScript can be included within Web pages, and how JScript functions are connected with different components of that page.

Events and Actions


To understand JScript's event-handling model, you must first think about the set of things that can actually happen on a Web page. Although there are many different things you can do with the browser, most of these have nothing to do with Web navigation. When you save a page as text, print a page, or edit your favorites list, you are not actually navigating the Web. In these cases, you are using some of the graphical capabilities of the browser, which are independent of the Web. To understand which browser actions correspond to JScript events and which do not, it is important to distinguish those actions that actually cause (or might cause) some change in the Web page being displayed. From the user's standpoint, the number of such actions is actually quite limited. In fact, there are really only two types of top-level actions: The user can navigate, or the user can interact with an element of an HTML form. Navigation means to change from one Web page to another, or perhaps to open a completely new page in a new window. Interaction with the contents of an HTML form means activating one of the elements in that form (clicking a button) or changing one or more of the elements in such a form that can be changed (editing a text field).

Navigation Actions and Events

In the navigation category, you can distinguish the following actions:


q q q q

Selecting a hypertext link Moving forward or backward in the history list Opening a new URL (possibly in a new window) Quitting the browser

In most of these cases, the current page will be unloaded, which means it will no longer be visible in any browser window. In several of these cases, a new page will be loaded, which means its contents will be displayed in a browser window, perhaps a new one created specifically to display this particular page. Anyone who has used the World Wide Web realizes that selecting a hypertext link may not successfully take you to another. The machine to which that link points may be down or simply inaccessible. The link may even be dead, meaning that it does not point to a valid destination. Selecting an inaccessible or dead link may unload the current page without loading a new page. Internet Explorer typically displays a blank page or posts an error message. You may or may not be left on the current page, depending on the type of error. A sample error alert from IE is shown in Figure 3.1. Figure 3.1 Attempting to access a nonexistent URL results in an error message in Internet Explorer. These events, loading and unloading a page, are the two document-level events that can be handled by JScript. This means that it is possible to write JScript code, contained within the HTML definition of a page, that will be executed whenever that page is loaded. You can also have code that is executed whenever that page is unloaded. It is important to realize that loading and unloading are two separate, unrelated events. For example, when you attempt to activate a link that leads to a nonexistent or blank page, the current page is unloaded, but nothing is loaded in its place. In order to return to the last valid Web page, you must use one of the navigation controls. For example, if you select Back in Internet Explorer, the last page you visited is reloaded. There are two additional events that are vaguely related to navigation. These events are the following:
q q

mouseOver mouseMove

When you move the mouse over a hypertext link, a mouseOver event is generated. This event is not associated with clicking the link; it is associated with being poised to click it. This event can be used to give the user feedback, such as changing the color of the link or flashing it. The final event is the mouseMove event. This event is a Microsoft-specific extension of the mouseOver event. It also occurs when you move the mouse over a hypertext link. The difference is that this event can be used to provide more information about the event, such as the current position of the mouse.

Forms Input and Events

We have now discussed the events that arise if you are using the browser to navigate the Web. Of course, you can also interact with your browser through the elements of an HTML form. Every form element that permits input is associated with one or more JScript events. We can broadly characterize the possible components of an HTML form as follows (Chapter 6, "Interactive HTML Objects," has a section on "Review of HTML Forms"):
q q q q

Buttons Text fields Selection lists Embedded objects

The first three components are standard parts of HTML. The final component, an embedded object created using the OBJECT tag, is a more recent addition that allows the Web page designer to embed a variety of active elements into an HTML page. For the moment, we will concentrate on the first three items on this list. See Chapter 12, "Scripting and ActiveX," for more information on embedded objects and the ActiveX technology, p. 341. Button Elements in Forms. Buttons come in five varieties, as follows:
q q q q q

Simple buttons Yes/No check boxes Option buttons Submit buttons Reset buttons

Simple buttons are defined using the HTML <INPUT TYPE="button">. Check boxes define options, which are either off (not checked) or on (checked). These are created using an <INPUT TYPE="checkbox"> directive. Option buttons use the <INPUT TYPE="radio"> directive, and permit the user to select exactly one of a set of choices. Submit buttons and reset buttons are very special. Submit buttons, created by <INPUT TYPE="submit">, are used to end input operations on a form. When the Submit button is pressed, the contents of the form are packaged and sent to the URL target specified in the ACTION attribute of the <FORM> definition. Reset buttons bring the form back to its initial state, wiping out any input the user has performed; they are specified as <INPUT TYPE="reset">. Figure 3.2 shows a simple HTML form with all five button types; it was generated by the HTML file ALLBUT.HTM.

TIP: Hidden fields on HTML forms do not generate JScript events.

Figure 3.2

All five types of HTML buttons have corresponding JScript events. The one thing the five types of buttons have in common is that you click the button to achieve its effect. Because this is an extremely common action, the JScript event model defines click as one of its HTML form events. This event is generated by each of the five button types. In addition, when a form is actually submitted, a submit event is generated. The submit event is really owned by the form being submitted, and not the Submit button that causes it. Text Elements in Forms. There are three types of text items possible within an HTML form, as follows:
q q q

Text fields Textareas Password fields

Single-line text fields are created with an <INPUT TYPE="text"> directive. Any text you type in a text field is displayed as you type it. This behavior is known as echoing the input. Single-line text fields that are created using <INPUT TYPE="password"> do not echo their input. Multiline text fields are created with the TEXTAREA tag, and are usually called textareas. An HTML form showing all three types of text elements is shown in Figure 3.3, created from the file ALLTXT.HTM. Interacting with text is more complex than interacting with a button. There are more things you can do with text. You can click in the text field, enter text, edit text, select text, and decide you are finished with the text and move on. Figure 3.3 HTML text elements generate several different JScript events. What are the events JScript generates in response to these various actions? JScript uses a text manipulation model that will be familiar to anyone who has ever used a windowing system. It defines four events that are associated with text fields and textareas, but not passwords fields--change, select, focus, and blur. The first two should be self- explanatory. The change event is generated whenever any text is changed, and the select event is generated whenever text is selected. Selecting text is more than simply clicking in the editable text field or textarea. It means actually highlighting a portion of the text with the mouse or arrow keys.

NOTE: Password fields do not generate JScript events. This was a conscious design decision to prevent malicious script code from diverting password text.

The events focus and blur are a little more involved. A text field or textarea is said to have focus when it is currently accepting input typed at the keyboard. Clicking anywhere inside a text item is certain to give it focus, and simply moving the mouse over the text field may do so, as well. blur

is the opposite of focus. blur occurs when the text item no longer has focus. This may happen because some other item now has the focus, or because the focus has simply been lost. You will notice that if you position the mouse over a graphic (other than an imagemap), you can type until your fingers are sore, but nothing happens. This is a case where nothing has focus. Selection Elements in Forms. Selection lists are defined by the SELECT tag; their options are enumerated using the OPTION tag. They operate almost the same as text items; they are capable of generating focus, blur, and change events. Paradoxically, selection lists do not generate select events. You might well wonder why four event types are needed for text and three for lists. This is clarified later in this chapter. Figure 3.4 summarizes the events understood by JScript and the HTML elements that generate them. The topic of text events is covered in much greater detail in Chapter 6, "Interactive HTML Objects," particularly in the section on "Manipulating Text Fields," p. 163. Figure 3.4 JScript events model different types of user interaction with a Web page.

Actions that Are Not Events


Anything not mentioned in the previous two sections should be considered an action, not a JScript event. Scrolling a window, reading newsgroups, or answering mail are certainly actions, but they are not events. Using the Back, Forward, or Home buttons on Internet Explorer's toolbar are not really JScript events, but they ultimately result in JScript events being delivered to the current page, because they unload the current document. Creating an entry in the favorites list (hotlist) is not even remotely related to JScript events, because it does not affect the current page at all. How does one distinguish actions that might possibly be events from those that are not? The rule is that if an action affects or changes the current page, it is associated with one or more JScript events. It might be argued that scrolling or resizing a window affects the current page, and should therefore result in some kind of event. Those of you who have programmed any kind of windowing system know these are often called visibility, or window damage, events. JScript takes a more literal definition of a page. No matter how much or how little of a Web page is visible, it is still the same page. Even if you read only the cartoons in The New Yorker, the articles are still there, unchanged.

JScript Code in HTML


So far, we have talked about JScript as a language, and we have talked a bit about HTML, but we have not talked about how JScript is used in HTML. Event handlers are the glue that link HTML elements with JScript code, but how is it done? This section addresses this question. The answer has two parts: how JScript is included or referenced in a Web page, and how event handlers are attached to HTML items.

The SCRIPT Tag

In the most general sense, every Web page is constructed from HTML statements that divide the page into two parts: the <HEAD> and the <BODY>. The HTML directives within the context of the <HEAD> give information about the page, while those in the <BODY> make up the page itself. In most simple HTML documents, the <HEAD> usually contains only the <TITLE>. It can also contain a BASE tag which specifies a pathname that should be used to resolve relative HREFs within the document, and one or more LINK tags, which indicate the relationship of this document to one or more other documents, such as the browser's home page. The HEAD section of an HTML document can also be used to contain the JScript code for your event handlers. While it is not absolutely necessary for all JScript code to go with the <HEAD>...</ HEAD> delimiters, it is an excellent idea because it ensures that all JScript code has been defined before any of the <BODY> of the document is seen. In particular, if the document has a handler for the load event, and that event was triggered before the event handler code had been read, an error would result because the event-handler function would be undefined. Syntax of the SCRIPT Tag. JScript code is introduced with the SCRIPT tag. Everything between this tag and the closing /SCRIPT tag is assumed to be some kind of client-side script code such as JScript. The syntax for the SCRIPT tag is: <SCRIPT LANGUAGE="LangName" [SRC="URL"]> The element LangName gives the language that is used in the subsequent script code; this should be JavaScript. Internet Explorer will also accept JScript and VBScript (for scripts written in the Visual Basic Scripting language). For maximum portability, you should specify your script language as JavaScript. This will give it a fighting chance of running on other browsers that support some version of JavaScript such as Netscape Navigator. If the SRC attribute is specified, it should reference an URL containing code in the script language. For JScript, this should be a valid URL for a file containing the JScript code. The file name should have the suffix .JS. If the SRC attribute is given, then the <SCRIPT> can be immediately terminated by a </SCRIPT> directive. A <SCRIPT> block that loads JScript code from a file named CLICK.JS in a directory jscode relative to the document base would look like this: <SCRIPT LANGUAGE="JavaScript" SRC="jscode/click.js"> </SCRIPT> If the SRC attribute is not given, it is expected that all the code between <SCRIPT> and </ SCRIPT> is the script source itself. In the glorious future, when the overwhelming majority of browsers understand the SCRIPT tag, or at least benignly ignore it, the JScript source may be given literally. Until then, it is recommended that source included between <SCRIPT> and </SCRIPT> be enclosed within the HTML comment delimiters <!-- and -->. A simple example showing a single JScript function is shown in Listing 3.1.

CAUTION: Use the C-style comments // and /* */ inside JScript code. Never use

HTML comments inside JScript.

Listing 3.1 A JScript <SCRIPT> with a Single Function


<SCRIPT LANGUAGE="JScript"> <!-function dontclickme() { // an ominous button click handler alert("I told you not to click me"); return( false ); } <!-- end script --> </SCRIPT> Use of HTML Comments. The function in Listing 3.1 does not do much; it merely uses the alert () function to pop up a warning dialog box with its argument as the message. Presumably, this function is the click event handler for a button you don't want the user to press. The important thing to notice about this simple example is the paradoxical but important use of HTML comments. The entire script body is enclosed with a comment, and the comment close --> is also paired with a second, seemingly redundant, comment start <!-- on the last line. At present, you should structure your script according to the following rules:
q q q

Place the comment start (<!--) on a line of its own. Follow it with your JScript code. Terminate the code with <!-- and --> on its own line.

It is also possible to terminate the script code with a line like //->, but the preceding method suggested is a bit more general. You should use this magic incantation not because it makes sense, but because it works. Note that JScript code referenced through an SRC URL should also follow these rules, as if it had literally been included in the <SCRIPT> block. Note also that you may have both a JScript SRC URL and literal JScript between <SCRIPT> and </SCRIPT>. In this case, the URL referenced by the SRC attribute is read and processed before the literal JScript. CAUTION: HTML comments are one of the least conforming areas of HTML. Most browsers deviate a little from the HTML standards, and some deviate a lot. The preceding comment rules may change in the future, and may be implemented differently on different browsers.

Processing <SCRIPT> Code. There are two important aspects to JScript code defined by or within a SCRIPT block. The first important principle is that this JScript code is not executed--it is merely read and checked for syntax errors. When the browser sees the code shown in Listing 3.1, it does not execute the dontclickme() function, it merely recognizes that this function is a JScript function,

and saves the definition of that function for later use. This is precisely the opposite behavior of normal HTML. When you say <HR> in an HTML document, you get a horizontal rule. You don't get it immediately, but you do get it when the browser has finished laying out the page (assuming that there are no HTML errors, of course). This is the way that most interpreted languages work, however. If you create a Sub in BASIC, a defun in LISP, or a proc in TCL, it is not executed when it is read. Instead, the interpreter parses it, which means that it scans through the function looking for obvious syntax errors, such as unbalanced parentheses, and records the function's definition for later use. The function is used only when it is called. In JScript, functions are most often called by events. Binding in JScript. Another critically important aspect of JScript is that it carries out dynamic binding. Binding refers to the way in which names of things, such as variable names, function names, and object names, are associated with the things themselves. If you call the function dontclickme from Listing 3.1 by saying dontclickme(), you are not actually referring to the function itself; you are referring to the name of the function. "The Song of the Volga Boatmen" is really the name of that song; it is not the song itself. If you want the sheet music, you go to your favorite music store and ask for it by name; most people do not go in and begin singing, "Eh-eh uxhnyot..." There are two general approaches to binding: static binding and dynamic binding. Many languages, particularly compiled languages such as C, C++, and Java, often insist on static binding. This means they require that they be able to find all named references when a program is compiled. (Of course, with the advent of dynamically loaded libraries, this rule was relaxed a bit.) JScript uses the more liberal form, dynamic binding. JScript attempts to resolve names only when they are used. Dynamic binding has several consequences. In the first place, if the function dontclickme() is never called, then it can contain all but the most hideous syntax errors and they will never be found. If dontclickme is the event handler for a button, and no one ever presses the button, its problems are never exposed. Even if dontclickme() is absolutely perfect, but the event handler is erroneously declared to be a function named noclickme(), this mismatch will not be detected until someone finally chooses to press the button. JScript will only then try to find a function named noclickme(). It will fail, and an error will result. Dynamic binding is often called runtime binding or late binding, because the binding process takes place only when the JScript interpreter attempts to run the code. TIP: Always check meticulously to ensure that the function, object, and variable names used in HTML match those in the JScript code.

Dynamic binding has its advantages and disadvantages. Dynamic binding is used by many interpreters because it simplifies the language, and makes it very easy to add in new functions. Since there is no brooding and melancholy compiler to satisfy, it is possible to build up a complex JScript application incrementally. Even if you really need an event handler for every possible event, you can start out with one or two handlers, make them work, and then gradually add more complexity. The disadvantage of dynamic binding should be clear from the previous discussion. There is very little error-checking. When the JScript interpreter is reading all the code in the SRC URL, or

processing the code between <SCRIPT> and </SCRIPT>, it is performing some checking but it is by no means performing an exhaustive analysis of the code. Errors, particularly mismatched names, are not found until the erroneous code is executed. To see a more complete example of this, look at the HTML page defined in Listing 3.2.

Listing 3.2 ex32.htm--An Illustration of Dynamic Binding


<HTML> <HEAD> <TITLE>A Potentially Dangerous JScript Page</TITLE> <SCRIPT LANGUAGE="JScript"> <!-function dontclickme() { // button click handler alert("I told you not to click me"); } <!-- end script --> </SCRIPT> </HEAD> <BODY> <FORM METHOD="POST" ACTION="mailto:me@myhost.com"> <INPUT TYPE="button" NAME="mycheck" VALUE="HA!" onClick="dontclickme ()"> </FORM> </BODY> </HTML> If you copy this code, found in EX32.HTM in the directory for Chapter 3 on the CD-ROM, into a local file, change the e-mail address in the form's ACTION to your own e-mail address, and then read that file into your browser, everything will be fine. Notice that the click event handler for the button is declared using the HTML attribute onClick="dontclickme()", which tells JScript that when this button is pressed, the function dontclickme should be called. (The exact syntax for declaring event handlers is discussed in the next section.) If you now click that button, you should see something like Figure 3.5. Figure 3.5 Clicking an HTML button invokes a JScript event handler that displays an alert. So far so good. The name of the event handler in the HTML statement that created the button matches the name of a JScript function in the SCRIPT block. Now try the following experiment. Change the handler declaration from: onClick="dontclickme()" to

onClick="noclickme()" and then read that file into your browser. You will notice that the initial appearance of the HTML page is exactly as before. No errors have been reported. If you attempt to click the button labeled HA!, your browser reports an error, and the alert dialog box shown in Figure 3.5 does not appear. This is dynamic binding at work. JScript did not know that the function named noclickme does not correspond to any currently defined function until the user action forced it to try to find one. Technically, the function name noclickme is said to be unbound. It might seem that dynamic binding is a great potential source of error without providing many benefits as compensation. As you will see when we discuss objects in Chapter 4, "JScript Objects," objects may be defined and even modified on-the-fly. Dynamic binding allows you to refer to things that do not yet exist, but that will exist when the event handler that uses them is actually called. Dynamic binding, like the loose typing provided by JScript's var, is a two-edged sword. It must be used with care, but is very powerful. See the "Defining Your Own Objects: The new Statement" section of Chapter 4, "JScript Objects," for more information on creating and modifying JScript objects. Let's summarize these two critical points about JScript parsing and execution, because they will dominate our thinking for several chapters to come:
q

JScript code is parsed when it is seen in a SCRIPT block; it is executed only when an event occurs. JScript names are resolved when they are executed, not when they are parsed.

Declaring JScript Event Handlers


The previous section demonstrated that JScript functions are executed only in response to events. We also know that events themselves occur only when some interaction with or change to the current HTML page occurs. There must be a way in which we can link events to JScript functions in HTML. In fact, we have already seen one such example of this in Listing 3.2. The mechanism is known as the event-handler declaration. Event-handler declarations look exactly like ordinary HTML attributes. Each attribute name begins with the word on and is followed by the event name, so that onClick is the attribute that would be used to declare an event handler for the click event. The full declaration of an event handler looks like this: onEvent="jscriptcode" Attribute names are not case-sensitive, following the usual HTML convention. It is good practice, however, to use the coding style shown in the preceding line of code, with on in lowercase and the event name with an initial capital. This helps to distinguish it from other attributes, which are often

fully capitalized. The value of the attribute is a set of JScript code. The code may be included literally (known as inline JScript) or it may reference a JScript function. We can completely remove the dontclickme() function of Listing 3.2 and write the button statement as: <INPUT TYPE="button" NAME="mycheck" VALUE="HA!" onClick="javascript:alert(`I told you not to click me');"> This has two disadvantages. First, it tends to lead to very long HTML statements. There is very little you can accomplish in only a few characters. If you have hundreds of characters between the opening (<) and the closing (>) of an HTML statement, it will almost certainly be very hard to read, and, if it is too long, may cause your browser to choke. It is also not modular. As you add event handlers for different HTML elements, you may well find that there is a lot of common code. Each of the button handlers might use a variation of the same code. Such common code should always be encapsulated in a JScript function, rather than being repeated in several places.

TIP: Declare all event handlers as JScript functions. Avoid inline JScript code.

One thing to notice about this example is the fact that the value of the onClick attribute is a quoted string. This follows standard HTML convention. Therefore, to include a string within the value of the attribute, we must alternate `' quotes with "" quotes. This follows the JScript standard for strings, as we learned in the "Implicit Data Types in JScript" section of Chapter 2, "JScript: The Language." If you modify the dontclickme function to accept a string argument, you must carefully use quotes when passing in literal strings. Listing 3.3 shows a modified version of dontclickme, called donteventme, and the HTML event-handler declarations that reference it. It can be found in the file ex33.htm on the CD-ROM.

Listing 3.3 ex33.htm--A JScript Function Can Be Shared by Several Event Handlers
<HTML> <HEAD> <TITLE>An Uncooperative JScript Page</TITLE> <SCRIPT LANGUAGE="JScript"> <!-function donteventme( str ) { // generic diffident handler alert("I told you not to " + str + " me"); } <!-- end script --> </SCRIPT>

</HEAD> <BODY> <FORM METHOD="post" ACTION="mailto:me@myhost.com"> <BR>No<INPUT TYPE="checkbox" NAME="mycheck" VALUE="HA!" onClick="donteventme(`click')"> <SELECT NAME="mysel" onChange="donteventme(`change')"> <OPTION SELECTED>Nope</OPTION> <OPTION>Not Me</OPTION> <OPTION>No Way</OPTION> </SELECT> </FORM> </BODY> </HTML> In this example, the function donteventme is called whenever the check box is checked or any selection is made on the selection list. The alert function within the donteventme constructs an uncooperative message based on the function's string argument str. Although this example accomplishes no useful work, it is a perfect template for a JScript page. In general, a JScript page has the following three components:
q q q

JScript functions inside a <SCRIPT> block, usually within the <HEAD> of the document Noninteractive HTML within the document's <BODY> Interactive HTML with event-handler attributes whose values are JScript functions

You now know how to declare event handlers in general. The next section shows exactly which handlers can be associated with specific HTML tags, and gives various examples of how these event handlers are used.

CAUTION: If you use the HTML IMG directive without assigning values to its WIDTH and HEIGHT attributes, event handling may be compromised. This limitation exists in Internet Explorer and Netscape Navigator. Make certain that you always include these attributes if you are using images together with JScript.

Using JScript Event Handlers


JScript events occur at three levels--at the level of the entire Web document, at the level of an individual <FORM> within the document, and at the level of an element of a <FORM> within that document. At the same time, any particular element at any of these three levels may result in more than one event. For example, you have already seen that text items can generate up to four different events, depending on how they are manipulated. In this section, we examine each level and see which handlers are appropriate for the HTML elements within that level. As you might suspect, most of the

action is at the lowest level, within HTML forms.

Document Level Event Handlers


The HTML BODY tag is the container that holds the descriptive content of an HTML page. Just as the material in the HEAD section is about the page, the material between <BODY> and </BODY> is the page. The BODY tag can contain two event-handler declarations using the onLoad and onUnload attributes. A JScript page might have a BODY declaration that looks like this: <BODY onLoad="loadfunc()" onUnload="unloadfunc()"> The onLoad="loadfunc()" attribute declares a JScript handler that will handle the load event. The load event is generated after the entire contents of the page, namely the HTML between <BODY> and </BODY>, have been read, but before they have been displayed. The onLoad event handler is an excellent place to perform any one-time initialization. It can also be used to display a splash screen containing company, product, or copyright information. It can even launch a security dialog box that permits only authorized users, with an appropriate password or key, to completely load the page. The onUnload="unloadfunc()" attribute declares an event handler that is invoked whenever the page is unloaded. This happens when the user executes any action that brings up a new page in the same browser window. An unload event does not occur if a new page is opened in a new window. Even if a new page is not successfully loaded, the current page may still be unloaded, and the unloadfunc is called in that case. An onUnload event handler can be used to ensure that there are no loose ends, and to perform any cleanup necessary. For example, if the user has filled out a form, but has failed to press the Submit button, the onUnload handler should inform the user of that fact. It could even submit the form itself, based on the user's response. Note that both the onLoad and onUnload handlers are optional. There are two final document-level event handlers, although they are not associated with the BODY tag. Any HTML link can declare an event handler for the mouseOver or mouseMove events, which both occur when the user places the mouse over the HREF of that link. This can be used to achieve a visual effect or to perform some special processing before the user actually tries to access the link. Listing 3.4 shows a slightly fanciful example. This code can be found in the file ex34.htm on the CD-ROM.

CAUTION: In the current implementation of JScript, links have event handlers, but anchors do not. This means that you must catch navigation events by attaching event handlers to links. If any of your links point to anchors in the same document, the event must be handled at the link, not at the anchor.

Listing 3.4 ex34.htm--Using the mouseOver Event to Mediate Access


<HTML> <HEAD> <TITLE>A Nationalist JScript Page</TITLE> <SCRIPT LANGUAGE="JScript"> <!-function warnthem( lnk ) { // mouseOver event handler var theirhost = lnk.hostname; // 2; get hostname of link var domain = "", lastdot = 0, len = 0; len = theirhost.length; // 4; string length of hostname lastdot = theirhost.lastIndexOf("."); // 5; find last dot domain = theirhost.substring(lastdot+1, len); // 6; last part of hostname if ( domain == "zz" ) { // 7; warn about country "zz" alert("Country zz only has 1200 baud modems"); } } <!-- end script --> </SCRIPT> </HEAD> <BODY> <HR> Check out the new links to <A HREF="http://home.std.zz" onMouseOver="warnthem(this)">Zzland</A> and its neighbor <A HREF="http://home.xyzzy.xy" onMouseOver="warnthem(this)">XYville</A> <HR> </BODY> </HTML> This HTML creates a page with two elements--links to the fictitious home pages of the countries Zzland and XYville, and sets up a mouseOver event handler for those links. Note that the event handler function warnthem is called with an argument this: The special keyword this is used to refer to the current JScript object. When the warnthem function is called, its parameter lnk is filled in with the object that represents the link over which the mouse just moved. The this keyword and other object-oriented concepts are discussed in Chapter 4, "Jscript Objects," in the section, "Defining Your Own Objects: The new Statement," p. 85. Statement 2 extracts the hostname part of that object, which in this example could be either home. std.zz or home.xyzzy.xy, depending on where the mouse is located. The next three statements use some of the string object functions (see "String Content Methods," in Chapter 4, "Jscript Objects") to tear off the last part of this fully qualified hostname, namely zz or xy, and save it in

the variable domain. This variable is then tested against zz in statement 7. If the test passes, an alert is put up to warn the user that the connection to the zz home page will take longer due to slow modems. Links can also have click event handlers, so this code can be modified not only to warn the user, but also to abort the connection, if necessary. The result of placing the mouse over the Zzland link is shown in Figure 3.6. Figure 3.6 JScript event handlers can be used with any hypertext links. The mouseMove event is almost identical to the mouseOver event. The only difference between the two is that the event handler for a mouseMove event is called with four arguments: the current state of the SHIFT key, which buttons are currently pressed, and the x and y coordinates of the mouse. Unfortunately, this event cannot be easily used with the type of HTML elements we have described so far. Its usage will be more fully discussed in Chapter 13, "More About ActiveX."

Submit Event Handlers in the FORM Tag


The FORM tag is used to begin the definition of an HTML form. It includes attributes from the METHOD to be used in submitting the form and the ACTION to be taken, and may also include a single type of event handler attribute, the onSubmit attribute. The syntax for a FORM tag is the following: <FORM NAME="formname" ... onSubmit="return submithandler()">

TIP: Put event handler attributes last on the attribute list of an HTML tag. This makes them easy to find and modify during debugging.

The onSubmit handler is invoked when the form's contents are about to be submitted. This is a toplevel action that applies to the entire form. It is also possible to specify an onClick action on the Submit button in a form, as you shall see in the section, "Button Click Events." The natural use for an onSubmit handler is to validate the contents of a form. The submission proceeds if the contents are valid, and is canceled if they are not.

CAUTION: In order to use a submit handler to cancel a submission, it is essential to use the word "return" before the submit handler's name, as shown earlier. If the "return" is omitted, the submit handler will be called, but the form will always be submitted.

Listing 3.5 (file ex35.htm on the CD-ROM) shows a very simple form with a single element, an editable text field. The value of the field is supposed to be a number between 1 and 9. The submit handler function checkit is called when the form is submitted. It validates the user-entered quantity and acts accordingly.

Listing 3.5 ex35.htm--Form Content Can Be Validated Using an onSubmit Handler


<HTML> <HEAD> <TITLE>A Simple Form Validation Example</TITLE> <SCRIPT LANGUAGE="JavaScript"> <!-function checkit() { // submit validation function var strval = document.myform.mytext.value; // 2; input text value var intval = parseInt(strval); // 3; convert to integer if ( 0 < intval && intval < 10 ) { // 4; input ok return( true ); // 5; allow submit } else { // 6; input bad - tell user alert("Input value " + strval + " is out of range"); return( false ); // 8; forbid submit } } <!-- end script --> </SCRIPT> </HEAD> <BODY> <HR> <FORM NAME="myform" METHOD="post" ACTION="mailto:me@myhost.com" onSubmit="return checkit()"> <P>Enter a number between 1 and 9: <INPUT TYPE="text" NAME="mytext" VALUE="1" SIZE="10"></P> <BR><INPUT TYPE="submit"> </FORM> <HR> </BODY> </HTML> It is worthwhile to examine this example in some detail, as it exposes a number of points that are more thoroughly discussed later in this chapter. Let us consider the HTML in the <BODY> first. The FORM statement creates a form named myform with our usual fictitious mailto destination. It also contains an onSubmit attribute that specifies checkit() as the JScript function to call when the form is about to be submitted. Like all of our previous event handlers, this one takes no arguments. You will see very shortly that it is not only possible to pass in arguments, but it can also be very beneficial. For a document this simple, however, it is not necessary.

The first INPUT tag establishes an editable text field named mytext, which can hold up to 10 characters, and that will be initialized to the string "1". The second INPUT tag puts a Submit button just below the input text field. Neither of these INPUT statements has any handler attributes, although they could. What happens next? If the user types in any text, or does anything except press the Submit button, then nothing special happens. This example does not process any events other than the submit event, so changes in the text field or navigation actions do not result in any JScript code being executed. If the user does press the Submit button, then the myform form tries to submit itself. This triggers the submit action, which results in its event handler, checkit(), being called. The checkit function does two somewhat obscure things. In statement 2, it sets the local variable strval equal to the value of document.myform.mytext.value. We know from the "Functions and Objects" section of Chapter 2, "Jscript: The Language," that the right side of this expression must be an object reference--in fact, a reference to an object within an object within an object. It is reasonable and correct to assume that the myform subobject corresponds to the HTML form named myform within the current document, and that the mytext subobject corresponds to the HTML editable text field named mytext inside myform. This windy construct transfers the value of that text field into the local variable strval. In statement 3, an attempt is made to convert this string to an integer using the built-in function parseInt. The putative integer is stored in intval. See the sections, "HTML Objects" and "Built-In Functions" in Chapter 4, "JScript Objects," for more information on how to manipulate HTML fields. In statement 4, our validation test is performed. If the string in the text field did represent an integer between 1 and 9, inclusive, this if test passes and the checkit function returns true in statement 5. This is a message from JScript to the browser that the submission may complete. If the text field was out of range, the else pathway in statement 6 is taken. Note that parseInt returns 0 if its argument cannot be parsed as an integer. This means that if the user entered "five" in the text field rather than "5", the value of intval will be 0, and the else clause will be taken. Statement 7 puts up an alert dialog box telling the user that the value was out of range. It contains the string representation of the value. This is useful, since the alert dialog box may be inadvertently positioned over the text input field. Finally, statement 8 returns false, indicating that the submit operation should not complete. The outcome of entering a value that is out of bounds is shown in Figure 3.7. Figure 3.7 JScript submit handlers are often used to validate form input. It should be stressed that if the event handler had been declared as onSubmit="checkit()" the function checkit() would still be called whenever the Submit button was pressed, but no validation would take place. The form would always be submitted in this case, even if the input value

is out of range. In this case, the return code from the checkit() function is ignored. The version that we used in Listing 3.5, onSubmit="return checkit()", ensures that the submission is canceled if checkit() returns false. In this particular case, it is important to give the mytext text field an initial value of 1. This ensures that if the user clicks the Submit button without altering that text field, it will have an acceptable value, and the form will be submitted. In many cases, just the opposite is true. The whole point of a catalog order form is to persuade the user to enter critical information, such as his or her name and email address. In this case, it's a good idea to initialize the text field with a deliberately invalid value, so that if the user hits Submit without typing anything, the form is not submitted. Chapter 6, "Interactive HTML Objects," and Chapter 16, "Creative User Interaction," provide several more sophisticated examples of customized user interaction using JScript.

NOTE: Always give the user meaningful feedback on inappropriate input or other error conditions. Indicate why and where the error occurred, not just that an error occurred. Be brief, but specific.

Event Handlers in <FORM> Elements


Almost all form elements may have one or more event handlers. The type of event handlers permitted on a given element depends on the type of element itself. You have already seen the linkage between events and HTML entities in Figure 3.4. Broadly speaking, buttons can generate click events, and text and select items can generate focus, blur, select, and change events. The one potentially confusing aspect of this organization of events is that selection lists cannot generate the select event. This is because they have no editable text. We will not consider all possible events in this chapter, only a pithy subset. There are two important exceptions to the rule that all form elements can have handlers. The first exception applies to hidden items, those with <INPUT TYPE="hidden">. Since they cannot be seen, they cannot be changed by the user, and therefore cannot generate events. The second exception applies to individual OPTION elements within a SELECT selection list. The SELECT tag itself may have attributes declaring focus, blur, and change handlers, but the OPTIONs may not generate their own events. Any acquisition or loss of focus and any change in the item(s) that have been selected apply to the whole list, not to an individual element. Button Click Events. All button types within an HTML form can have click event handlers by adding an onClick attribute to their <INPUT> declaration. Simple buttons with a TYPE attribute of "button", "reset", or "submit" merely signal that they have been pressed. (Recall that the act of submitting a form may also be caught using an onSubmit handler attached to the <FORM> declaration.) Check boxes and option buttons also have values. Check boxes and individual option buttons can be asked whether they are on or off. A group of option buttons can also be asked for the

unique index of the button currently checked. One very common problem in HTML forms design is the issue of conflicting options. Users are often presented with a variety of different choices, which may even be spread out over more than one HTML form. Some combinations of choices may be invalid or dubious. Unfortunately, in standard HTML, there is no way to perform input validation of this kind without actually submitting the form and asking the ACTION URL whether that particular combination is acceptable. JScript event handlers are ideal for this kind of validation. As you will learn in Chapter 4, every HTML form element is also a JScript object. You have already seen some examples of this in Listings 3.4 and 3.5. Listing 3.6 shows two option buttons working together with a check box using a JScript onClick event handler. The code for this listing can be found in file ex36.htm on the CDROM. The initial appearance of this form is shown in Figure 3.8.

Listing 3.6 ex36.htm--Values of Different Form Elements Can Be Accessed in JScript


<HTML> <HEAD> <TITLE>Two Choices Work as One</TITLE> <SCRIPT LANGUAGE="JavaScript"> <!-function insok() { // make sure payment & ins choices are compatible var isgold = document.myform.payment[1].checked; // 2; gold checked var isins = document.myform.insurance.checked; // 3; insurance selected? var ok = null; // 5; if paying in gold without insurance then.. if ( isgold == true && isins != true ) { ok = confirm("Do you want insurance?"); // 6; ask for insurance if ( ok == true ) { // 7; yes, get insurance document.myform.insurance.checked = true; // 8; check it } } <!-- end script --> </SCRIPT> </HEAD> <BODY> <HR> <FORM NAME="myform" METHOD="POST" ACTION="mailto:me@myhost.com"> <STRONG>Payment Options</STRONG><BR> <HR> <INPUT TYPE="radio" NAME="payment" VALUE="1" CHECKED onClick="insok()"> Personal Check <INPUT TYPE="radio" NAME="payment" VALUE="2" onClick="insok()"> Gold Bullion

<HR> <INPUT TYPE="checkbox" NAME="insurance" VALUE="Ins"> Insurance? </FORM> <HR> </BODY> </HTML> The <BODY> of this page sets up a two-choice option button named payment, and a check box named insurance. The first button is selected, and the check box starts off unchecked. The option button group has the function insok as its click event handler. Whenever either of the buttons is clicked, the insok function is called. In statements 2 and 3, insok fetches the current value of the second option button named payment. Note that payment actually denotes the entire group of buttons, not any single option button, so that you must use the array reference payment[1] in order to refer to the second button (0-based indexing is used). That value is stored in the Boolean variable isgold. The variable insok gets the state of the insurance check box, which is also true if it is checked and false if it is not. A compatibility test is now performed in statement 5. If the option button group indicates payment in gold bullion, but the insurance button is not checked, then a confirmation dialog box is put up using the confirm() function in statement 6. Figure 3.8 JScript onClick handlers can be used to exclude invalid user input. The confirmation dialog box has OK and Cancel buttons. If the user presses OK, the function returns true; otherwise it returns false. The return value is tested in statement 7. If it was true, then the user does want insurance, and the method function value of the checked property of the myform. insurance object is set to true. Without worrying too much about what methods and properties really mean just yet, it is easy to infer that this assignment statement has the same effect as a click of the insurance button. That check box is now checked.

Troubleshooting: I modified the code shown in Listing 3.6. I added another group of option buttons to collect information about the user's income level, with its own event handler doinc(). I would like to force the insok() function to be called from the new event handler. Inside doinc(), I have a statement: myform.insurance.click(); This click() function is supposed to cause the insurance check box to be checked, but the handler is never called. Why? JScript has many functions such as click() that emulate user actions. These emulated actions do not generate events, however, so the corresponding event handler

functions are never called. There is nothing mystical about the event handler function insok()--it is an ordinary JScript function that happens to be linked to an HTML event. If you want to call insok() in your doinc() event handler, just do the following: insok();

Text Edit and Selection Events. HTML text <INPUT> fields with a TYPE attribute of "text" may declare event handlers for any combination of the four text events: focus, blur, change, and select. Multiline text input items created with a TEXTAREA tag may also have these handlers. Selection lists created with <SELECT> can generate all these events except select. The focus event is generated when the text item gets the input focus, usually as a result of a mouse click. Tabbing through form fields also moves the input focus. The blur event is generated when an item that had focus loses it. The change event is generated whenever something changes. In a text item, this results when any new text is entered or existing text deleted. In a selection list, it happens whenever a new selection is made, even in a list that permits MULTIPLE selections. The select event is generated when the user selects some text, usually by click-and-drag or double-click operations with the mouse. The select event is almost always accompanied by a visual cue, usually by the selected text becoming highlighted or changing color. These events can be used to obtain very fine control over the content of text or selection list items. The most common application is to use the change or blur events to ensure that a text field has an appropriate value. If you ask the user to enter his or her birthdate, for example, and provide separate fields for the month, day, and year, you will almost certainly want to make sure that the value of the day field is a number between 1 and 31. You might even go to greater lengths, and limit the day field's value based on the value of the month field. In any case, you want to avoid erroneous input such as "bleen." Text events can also be used to coordinate the values coming from multiple form elements, as we saw in Listing 3.6. Listing 3.7 (file ex37.htm on the CD-ROM) shows a linguistic application of the blur event for a TEXTAREA. The user is inspired to enter a sentence without a single instance of the letter e. If the user tries and fails, he is chided for his lack of creativity. Note that the blur event handler is called only if the user clicks outside the textarea, because blur is generated only when focus is lost. Parts II and IV of this book provide many more detailed examples of all the JScript events.

Listing 3.7 ex37.htm--An Example of JScripts Text Events


<HTML> <HEAD> <TITLE>A Literary Exercise</TITLE>

<SCRIPT LANGUAGE="JavaScript"> <!-function hasE() { // complain if there is an e var thestr = document.myform.mytarea.value; // 2; get textarea value var uthestr = thestr.toLowerCase(); // 3; convert to lowercase if ( uthestr == "" ) { // 4; no entry return; // 5; just return } if ( uthestr.indexOf("e") >= 0 ) { // 7; found an `e' alert("Alors! You've got an E in there!"); // 8; failed } else { if ( uthestr.length <= 20 ) { alert("Nice try, but too brief"); // 11; too short } else { alert("Congratulations!"); // 13; succeeded } } } <!-- end script --> </SCRIPT> </HEAD> <BODY> <P>The novel <I>A Void</I> does not contain a single &quote&quot. <BR> Can you create a sentence without one?</P> <HR> <FORM NAME="myform" METHOD="POST" ACTION="mailto:me@myhost.com"> <TEXTAREA NAME="mytarea" ROWS="5" COLUMNS="80" onBlur="hasE()"> </TEXTAREA> </FORM> <HR> </BODY> </HTML> The modus operandi of this example should be becoming familiar to you now. If the user types or clicks in the textarea, nothing happens. When he or she leaves the textarea and clicks elsewhere, a blur event is generated and the handler function hasE is invoked. This function gets the contents of the textarea into a local variable named thestr (in statement 2) and then uses one of the string functions to convert it to lowercase (statement 3). This saves a little time, as the function won't have to test for the presence of both e and E. The new lowercase string uthestr is tested against the empty string in statement 4. If there is no text, the function returns without complaint. If there is some text, but it has an e, the user is reprimanded in statement 8. If there is no e, but the text has less than 20 characters, the user is encouraged to try a more ambitious work in statement 11. If the text is long enough and has no e, the user is praised in statement 13. Of course, there is nothing preventing the user from entering gibberish such as zzzzzzzzzzzzzzzzzzzzzzzzz and being

congratulated anyway. Much more sophisticated checking would be necessary to ensure that the input was actually a sentence.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Chapter 10 A Java Tutorial


q

A Java Tutorial r The Java Language s Java and JScript Compared s Data Types in Java s Java Classes as Structured Data Types s Java Statements r Developing Java Applets s The Java Development Cycle s Java Compilers and the JDK s The APPLET Tag s A Simple Applet s Anatomy of an Applet r An Accounting Applet in Java s The init Method s The do1trans Method s The paint Method s Executing the Account Example Applet

A Java Tutorial
Some of the main topics in this chapter are
q q q q

Define and use Java methods and classes Create Java applets Use the Java development kit to compile applets Embed applets in a Web page

JScript is an extremely powerful tool for developing Web pages. You have already seen a number of significant applications using JScript in the preceding chapters. The complexity and power of applications that can be developed in JScript is almost unlimited. There are certain situations in which the Java programming language may be a better solution, however. The difference between JScript and Java is very much like the difference between hand tools and power tools. Anything you can do with a lathe, you can also do with a rasp, a hand saw, and sandpaper. It is quite possible to produce beautiful woodwork using only the simplest tools. One

gains time, and perhaps uniformity, by using a lathe. To do this, however, one must know how to operate a lathe properly, without losing fingers. (In this analogy JScript is the lathe.) JScript is a simpler language than Java, with fewer built-in functions, yet it is still extremely expressive. Java has a much larger set of capabilities, yet it is also a bit more difficult to use. The correct approach, of course, is to use all the tools that are available. Nevertheless, it is very important to realize when to pick up the fine-grit sandpaper and when to power up the lathe. This chapter introduces the Java language and describes its differences from JScript. The basic constructs of Java applets are explored and some simple examples are given.

The Java Language


If you have ever seen any Java code, you have probably noticed that it bears a substantial resemblance to JScript. A large part of the Java language is identical to JScript. There are, however, several significant differences between Java and JScript that are critical in learning how to use both tools effectively. These differences can be grouped into the following three categories:
q q q

The object models Interactions with the browser environment Language differences

The way in which the two languages handle objects is fundamental to how they are each used. Their interactions with the Web browser are also fundamentally different--the concept of an event is completely different in Java. Finally, the Java language is much stricter in its usage than JScript. Before we plunge into a detailed description of Java code, it is useful to look at these differences in a little more detail. Java and JScript are very different under the hood.

Java and JScript Compared


In Part II of this book, "JScript Objects," we took a very close look at objects in JScript. JScript objects are used to access the built-in mathematical, string, and date functions. JScript objects are also used to access and manipulate HTML elements inside JScript code. Java takes this objectoriented approach even further. Everything in Java is based on objects (known as classes in Java), and their properties (instance variables in Java) and methods. In JScript, you often create functions that are methods of your own objects. You are also perfectly free to have functions that are not methods. Event-handler functions are usually not method functions, for example. In Java, all functions must be methods of some object, and all variables must be properties of some object. In JScript, the focus is on responding to events. A user action produces an event that triggers a JScript event handler, which does something useful. In Java, user events are handled very differently. When the user loads a Web page containing Java code, in the form of a Java applet, the browser tells the applet to start. When the user leaves that page, the applet is told to stop. While JScript code is ultimately event-driven and intimately tied to its HTML environment, Java applets are much more independent. An applet may respond to a mouse click within its active area, but it won't be listening

for the sound of a Submit button being pressed. An applet is a little application that lives in its own world for the most part. JScript code is more like a Dynamically Loaded Library (DLL), which is activated in response to something. Finally, we know that JScript takes a very relaxed attitude toward variables and functions. Variables are typeless, and the distinction between functions, objects, and arrays is blurry at best. By contrast, Java is an extremely strict language. All Java variables have an explicit data type. Types may be converted to one another only under very well-defined conditions, and only by using explicit type conversion functions. Java also enforces static name binding, instead of JScript's dynamic binding. It is impossible (so they say) to reference an undefined function. See the "Dynamic Binding" section of Chapter 4, "JScript Objects," for a discussion of the namebinding concept. Java is actually a very small language when compared with other object-oriented programming languages such as C++. Nevertheless, it has a large number of capabilities. The extensive set of builtin functions and objects known as the Java class hierarchy, for example, implements an extremely rich and powerful set of tools for image manipulation and network access, among other things. This Java tutorial focuses on the core part of Java necessary to create meaningful and interesting Web content.

Data Types in Java


Java variables must be explicitly declared with a particular data type. Java is very similar to the C and C++ programming languages in terms of the types it supports. Java, however, rigidly specifies the size and representation of its various types, so that there can be no confusion. If you have ever tried to port a C program from a DOS or Windows environment with 16-bit integers to a UNIX or WindowsNT environment with 32-bit integers, you know from firsthand experience how frustrating such lowlevel problems can be. In addition to its primitive types, such as int, float, and boolean, Java also has object types, just like JScript. In Java, however, you must say which object was used to create a particular instance. The declarations that follow say that s is an instance of the String object, and that d is an instance of the Date object: String s; Date d;

NOTE: For the most part, Java statements are similar in form to their JScript counterparts. Every Java statement must end in a semicolon, however.

As you might suspect, these are uninitialized instances. The variables s and d are of type String and Date, respectively, but have no values yet. They are unbound, just as the JScript declaration: var myvar; creates an uninitialized (unbound) variable myvar. The only difference between the two languages is that in Java we at least know what the underlying type of s and d are, while in JScript, myvar is a complete mystery until it is given some value. There are several differences between the object models of Java and JScript as well as their terminologies. Note that Java refers to its objects as classes, unlike JScript. Java object members are referred to as instance variables, rather than properties. Instances and methods have the same meaning in both languages. Note particularly that Java has no independent functions, only methods. These differences arise from the fact that Java is both explicitly typed and strongly typed. In Java, every piece of data must have a type. Every structured data type, such as String, is a class, while the data itself is an instance of that class. This concept of strong typing pervades all of Java, and is reflected even in the differences in terminology with JScript. In Java, almost all the built-in data types are numeric. This is a reflection of the fact that everything that is more complex than a number is represented by a Java class. The built-in data types in Java are as follows:
q q q q q q q q

boolean byte char short int long float double

The boolean data is a 1-bit type, which may have the familiar values true and false. Java is more strict than JScript in that it does not allow you to use a numeric expression in a context in which a Boolean value is expected. You must say while ( true ) rather than while ( 1 ), for example, because the clause of a while statement must be a logical (Boolean) value. The byte, short, int, and long types are the basic fixed-point numeric types. All are signed quantities. They are represented using 8, 16, 32, and 64 bits, respectively. If you are a C programmer from either the 16- or 32-bit worlds, this may seem a little confusing. In the 16-bit world, int and short are mostly the same, while in the 32-bit world, int and long are often the same. Java is actually more explicit. All the basic types are platform-independent. Their sizes are fixed as part of the language itself. You may be wondering what the char data type is. Java has taken a very modern approach and adopted a standard known as the Unicode standard for character representation. Unicode is a way of

representing almost any character in any language of the world using a fixed Unicode sequence. Unicode sequences look like \uNNNN, where NNNN is a four-digit hexadecimal number. This is something like an extension to the escape sequences of the C programming language. In C, you can write "\007" to represent the character with ASCII code 7 (Ctrl+G, which usually makes the computer go "ding"). In Unicode, you can write "\u212B" to represent the Angstrom symbol and "\u1039" for the Tibetan Rinchanphungshad.

TIP: With the exception of Unicode characters, Java has the same syntax for literals as JScript.

CAUTION: What you see is not necessarily what you get with Unicode. Many browsers and most display devices are not able to handle properly most Unicode sequences. Avoid Unicode in your Java code unless you are sure your users have the appropriate fonts and software to display it.

The char data type is a Unicode character. It is 16 bits wide, and is an unsigned quantity, unlike all the other Java data types. This can also lead to some confusion for programmers who are familiar with 8-bit characters, since a char is twice as big as a byte in Java. One immediate consequence of the use of Unicode is that strings and arrays of bytes are not the same; some work must be done to convert from one to another. Another consequence is that if you ask a string such as Hiya how long it is, it will tell you 4. This means that it is 4 chars long, which is actually 8 bytes. The float and double data types are standard single and double precision floating-point data types. The Java language mandates that these data types conform to the IEEE (Institute of Electrical and Electronics Engineers) 754 standard, so that a float will always be a 32-bit quantity and a double a 64-bit quantity, with very precisely defined notions of accuracy, precision, and permitted maximum and minimum values. Imposing a particular standard may be pushy, but at least it ensures that correct implementations will all work the same way. On the surface, Java variables and JScript variables seem to behave in the same way. Because Java is a strongly typed language, unlike JScript, Java variables can be used only in much more restrictive ways. It is not possible to change the data type of a variable in Java, as it is in JScript. In order to convert between different data types, you must use explicit conversion routines. We'll see several examples of this, particularly in the final section of this chapter, "An Accounting Applet in Java."

Java Classes as Structured Data Types


Java would be very underpowered if it had only the built-in types listed in the previous section. Of course, it not only has these primitive types, it also has complex types that are built up from smaller components. These are classes in Java. They are very similar to JScript objects and also to the classes

of C++. In fact, the Java class model is a very simplified version of the one used by C++. Java has a very rich set of predefined classes, known as the Java class hierarchy. Some of the components of this hierarchy are described in the final section of this chapter. Still more are discussed in Chapter 11, "More About Java." In this section, we discuss the basic concept of a class and show how it is defined and used. The Java concept of a class is quite close to the JScript concept of an object. The primary difference is that Java is much stricter about how instances may be used, and has a more detailed set of rules that must be followed. For example, it is not possible dynamically to extend a Java instance, as it is in JScript. See the section on "Using Variable Length Arrays and Extended Instances" in Chapter 4, "JScript Objects," which describes how to extend JScript instances. A Java class is a collection of variables and methods. When a class is created, its variables and methods are defined as part of the class definition. Therefore, the shape of the class is fixed when it is created. Listing 10.1 shows a very simple Java class definition.

Listing 10.1 A Java Class for Keeping Track of Money


class Account { // name of the class is "Account" int ivegot = 0; // instance variable, initialized to zero void deposit ( int n ) { // method for adding money ivegot += n; } // method for determining how much is left int balance( ) { return(ivegot); } // method for attempting to withdraw money boolean withdraw( int n ) { boolean result; // local variable if ( n <= ivegot ) { ivegot -= n; result = true; } else { result = false; } return(result); } }

TIP: Java class names should begin with an uppercase letter. Instance names often

begin with a lowercase letter, and contain the class name of which they are an instance.

Listing 10.1 defines a class known as Account. It has a single instance variable, ivegot, which records the total amount of money stored in the Account. It is initialized to 0. It also has three method functions: deposit, balance, and withdraw. These method functions perform the operations specified by their names; they deposit money, get the account balance, and attempt to withdraw money. There are several things to notice about this class definition. The first, and most obvious, thing about the class Account is that all its components are declared inside the class definition. In particular, all the class methods are given explicitly as part of the class itself. Methods and variables are not attached, as they are in JScript--they are a required part of the definition itself. The second important aspect of these methods is the fact that each of them is declared with its own data type. The balance method is declared to be an int method, which indicates that it returns an int value, the amount of money left in the account given by the int ivegot. The balance method is said to have a return type of int. Similarly, the withdraw method has a return type of boolean; it returns a boolean quantity.

NOTE: The return type of a method must match the value returned. It is a serious error to attempt to return something whose type is different from the return type.

The void Keyword. The deposit method is interesting because it introduces a new keyword: void. The void keyword is used to indicate that nothing is returned. The deposit method simply takes its argument, adds it to the instance variable ivegot, and then falls off the end of its { } definition block. There is no return statement. void means what it says--there is nothing being returned. The same rule applies for the empty argument list of the balance method. This indicates that the balance function accepts no arguments. This is in contrast to the deposit and withdraw methods, both of which accept a single argument, which we are told is an int. Just as it would be an error to pass a floating-point value to deposit, it would also be an error to pass any value to balance, or to try to take the value of a method function declared to be void. If we assume myacct is an instance of the Account class, then both of the following statements would be in error by virtue of misusing the void type: int i = myacct.balance(0); // bad: void args int j = myacct.deposit(10); // bad: void return Declaring Java Classes. With the example of Listing 10.1 in mind, you can see the general pattern

for declaring both kinds of class members, namely instance variables and method functions. The general structure of a class declaration looks like the template shown in Listing 10.2.

Listing 10.2 Declaring a Java Class and Its Members


class Classname { // a class named Classname Type1 Var1; // instance variable Var1 of type Type1 Type2 Var2; // instance variable Var2 of type Type2 ... // more instance variables // Method Method1, return type RetType, arguments Arglist RetType Method1( Arglist ) { ... return( Thing ); // return statement if not void } // end of Method1 ... // more methods } // end of class definition This class declaration consists of three basic parts, as follows:
q q q

The class declaration line The instance variable declarations The method declarations

The class declaration line declares the name of the class. It is Java tradition that this name begin with an uppercase letter, as noted earlier. This makes it easy to distinguish class names from variable names (and from the names' built-in types) which traditionally begin with a lowercase letter. In Listing 10.1, we declared a class named Account. The instance variables are then declared immediately following the opening of the class definition, which is indicated by the opening bracket ({). It is possible in Java to declare instance variables anywhere outside a method definition, but it is simpler and easier to understand if they are all placed at the very top of the class definition. Our Account example had a single instance variable ivegot. Note that every instance variable must have a type, and may be initialized. The Account variable ivegot was initialized to 0, for example. As usual, it is good programming practice to initialize all instance variables to reasonable defaults, if possible. The method function should be placed after the instance variables have been declared. Each method function declaration is itself composed of the following four parts, all of which are mandatory for (almost) every method:
q q q q

The return type The method name The argument list The method body

The return type is given immediately before the name of the method itself. With one critical exception (constructor methods, which are described next), all methods must have a return type. If the method executes the return statement, it must declare what type of quantity it is returning in its return type. If the method does not return anything, it must declare its return type to be void. Java is very strict about mismatches of this form. The method name is the name by which the method is invoked. This is exactly the same as the function and method names of JScript, with one exception. If the name of a method is exactly the same as the name of the class, then the method is known as a constructor method, or simply a constructor. Later in this section, you will see how these are used. The argument list declares which arguments, if any, will be given to this method function. The argument list should contain the argument types, as well as the names of the arguments. In Listing 10.1, there is a method named deposit with a void return type and a single int argument named n; a balance method with int return type and no (void) arguments; and a boolean withdraw method, which also takes a single int argument named n, just like deposit. The argument list must match the arguments used exactly. We cannot call deposit with two arguments or with a string argument, and we cannot call balance with any arguments at all. Finally, the set of Java code between the opening and closing brackets ({}) constitutes the method body. The method body does the work of the method. In general, the method body may make use of its arguments and of the instance variables. The method function deposit is a perfect example of this. Its method body consists of a single statement: ivegot += n; which adds the argument n, the amount being deposited, to the instance variable ivegot. Method functions can also call other method functions within the class. Let's consider an example that makes use of the Account class. In this example, we will open an account, make a deposit of 100, and then make successive withdrawals of 40 and 70. The code to do this is shown in Listing 10.3. (Note that these deposits and withdrawals are not associated with any specific currency. The deposit of 100 could be 100 dollars, 100 francs, or even 100 coconuts.)

Listing 10.3 Using the Account Class


Account myacct; // 1; declare an instance of the Account class boolean gotit; // 2; got the money? myacct = new Account(); // 3; initialize it myacct.deposit(100); // 4; deposit 100 gotit = myacct.withdraw(40); // 5; try to withdraw 40 if ( gotit == true ) { // 6; got it System.out.println("Withdrawal ok"); // 7; print a message } else { // 8; didn't get it

System.out.println("Insufficient funds"); System.out.println("Balance: " + myacct.balance()); // 10; print balance } gotit = myacct.withdraw(70); // 12; try for 70 now if ( gotit == true ) { // 13; got it System.out.println("Withdrawal ok"); } else { // 15; didn't get it // 16; print failure message System.out.println("Insufficient funds"); // 17; print balance System.out.println("Balance: " + myacct.balance()); } This code shows a typical sequence of operations in Java. Statement 1 declares an instance of the class Account. It is an uninitialized instance, so it cannot be used until we initialize it. This initialization happens in statement 3 using the familiar new operator: myacct = new Account(); // 3; initialize it Note that the Account class is invoked as if it were a function (with no arguments). The variable myacct is now a fully initialized instance of the class Account, so we are free to use its methods.

CAUTION: Do not confuse instances with instance variables. Instances are structured data items created from classes using the new operator. Instance variables are variables contained within a class definition.

In statement 4, we make a deposit of 100, so that the ivegot now has the value 100. Similarly, statement 5 withdraws 40, so that ivegot is then reduced to 60. Both these statements invoke methods of the myacct instance, as follows: myacct.deposit(100); // 4; deposit 100 gotit = myacct.withdraw(40); // 5; try to withdraw 40 This withdrawal succeeds so that the boolean variable gotit, which holds the return value of the method function withdraw, is true. Therefore, the if test in statement 6 succeeds, and statement 7 is executed, as follows: if ( gotit == true ) { // 6; got it System.out.println("Withdrawal ok"); // 7; print a message }

We have enough experience to guess that System.out.println calls the println method of the subobject out of the system object System, and prints a message somehow.

NOTE: The dot operator (.) works the same way in Java and JScript. It is used to reference an element (instance variable, property, or method) of an instance.

We now grow bold and attempt to withdraw 70 from the account represented by the instance myacct, by calling the method function withdraw again in statement 12, as follows: gotit = myacct.withdraw(70); // 12; try for 70 now This time, it doesn't work, however, since the account holds only 60 at this time. If you examine the body of the method function withdraw in Listing 10.1, you see that it is quite careful to test and make sure that there are sufficient funds. In this case, therefore, myacct.withdraw returns false. The if test of statement 13 fails and the else pathway of statement 15 takes us to statement 16, which prints out a discouraging but accurate assessment of our financial state. Statement 17 is also invoked to print our balance, as follows: if ( gotit == true ) { // 13; got it System.out.println("Withdrawal ok"); } else { // 15; didn't get it // 16; print failure message System.out.println("Insufficient funds"); // 17; print balance System.out.println("Balance: " + myacct.balance()); } Statement 17 uses the method function balance to get the value, and also makes use of + as a string concatenation operator. This is one of the few cases in which Java relaxes its strict rules on data types. It is usually possible to use + to convert nonstrings into strings, but there are certain exceptions. We learn more about this topic in the next chapter. For the moment, just know that converting any of Java's built-in numerical types to strings, as line 17 does, is safe. This example probably raises several questions. Based on your experience with JScript, you are probably wondering why we need any of the methods of the Account class. After all, can't we just refer to the instance variable ivegot as myacct.ivegot, and use the following statements: myacct.ivegot += n; myacct.ivegot -= n; int howmuch = myacct.ivegot;

to deposit n, withdraw n, and get the account balance into the variable howmuch? This example code in Listing 10.3 is also very unrealistic. Banks do not simply let you open an account; they want you to open an account with an initial balance. There should be some way of specifying that initial balance when we call new, just as we do in JScript. Finally, this example is insecure. We really do not want anyone to have access to our account balance, nor do we want people to withdraw our money. They should be able to deposit as much as they like. All three of these observations are valid. To make this example more meaningful, we must introduce two more Java constructions--private instance variables and constructor methods. Private Variables. The basic deficiency of the class Account defined in Listing 10.1 is that the instance variable ivegot is completely wide open. After the account is opened (new is called to create an instance of Account), we can simply manipulate the balance directly. This makes the three methods of Account fairly useless, and is also very insecure. We would like to hide ivegot from prying eyes, and also restrict the withdraw and balance methods. Listing 10.4 shows a revised definition of the Account class that does this. This file is ex10_4.java on the CD-ROM.

Listing 10.4 ex10_4.java--A Safer Version of the Account Class


class Account { // new and private int ivegot = 0; // private int password = 29; boolean isopen = false; // improved Account 2; amount on deposit // 3; instance var for password 4; account actually has money

void deposit(int n) { // 5; anyone can deposit if ( n > 0 ) // 6; cannot deposit negative money ivegot += n; // 7; do the deposit /* Check account and make sure it is open Update the isopen variable */ isopen = ( ivegot > 0 ? true : false ); // 8; } // end of deposit method // 10; password protected balance method int balance(int pword) { if ( pword == password ) // 11; correct password return( ivegot ); // 12; return accurate balance else // 13; incorrect password return( -1 ); // 14; return bogus balance } // 15; end of balance method // 16; password protection here too boolean withdraw(int pword, int n) { boolean ok = true; // 17; ok to withdraw? if ( pword != password ) // 18; bad password ok = false; // 19; cannot withdraw if ( n > ivegot ) // 20; too much

ok = false; // 21; cannot withdraw if ( ok == true ) { // 22; withdrawal allowed ivegot -= n; // 23; update balance // 24; update isopen variable isopen = ( ivegot > 0 ? true : false ); } return(ok); // 26; return status } // end of withdraw method } // end of Account class This version of the Account class has three instance variables: ivegot, password, and isopen. The first two are declared to be of type int, and also have the special keyword private. A private variable is one that cannot be accessed outside the class. We can no longer refer to myacct.ivegot, nor can we refer to myacct.password, since both are declared private. We can, however, refer to the boolean variable isopen using myacct.isopen. This variable will be used to indicate whether the account has any money, so it is initialized to false. We can redundantly declare isopen as: public boolean isopen = false; using the public keyword. public is the opposite of private, and indicates that isopen may be accessed outside the class. By default, instance variables are public unless specified otherwise. The methods deposit, withdraw, and balance are now essential. Because these methods are all within the Account class, they are permitted to access its private variables, as well as its public ones. The deposit method illustrates this in a very simple way. In statement 6, it tests its argument to ensure that it is positive, so that no one can make a sneaky withdrawal by depositing a negative amount. If the test passes, then statement 7 is executed. It adds the argument n to the private variable ivegot. It also updates the public instance variable isopen in statement 8. If there is some money on deposit, the account is declared to be open (isopen is true); otherwise, it is closed (isopen is false). The following three statements constitute the body of the deposit method: if ( n > 0 ) // 6; cannot deposit negative money ivegot += n; // 7; do the deposit isopen = ( ivegot > 0 ? true : false ); // 8; update isopen The new version of the balance method now makes use of password protection. To successfully call this method function, a password must be supplied as the argument pword. This argument is tested against the private variable password. If the passwords match, the actual balance is returned via the statement return(ivegot) on line 12. If they do not match, -1 is returned in statement 14. Note that because external access to a private variable is prohibited, it is not possible to steal the password by saying: int ha = myacct.password;

It is also not possible to gain access to the balance without supplying a password. The statement: int left = myacct.balance(); will be instantly rejected by Java, because any call to balance() must have exactly one int argument. The withdraw method operates in a similar way. It now takes two arguments, the password argument pword and the amount to withdraw n. If the passwords do not match (pword ! = password on line 18) or the amount is too great (n > ivegot on line 20), the local variable ok is set to false. If ok remains true, both tests must have passed and the withdrawal takes place (statement 23). In this case, the status of the account is also updated in statement 24. If there is no money left, the account is automatically closed (isopen is set to false). Finally, the status of the transaction is returned using return(ok) on line 26.

NOTE: Variables declared inside methods are known as local variables. They may be accessed only within the body of the method in which they are declared.

This version of the Account class satisfies our security concerns. No one can tamper with our myacct instance and withdraw money or even get our balance without the proper password. The password and the account balance are hidden. However, we have allowed anyone to determine whether or not we have an active account using the public instance variable myacct.isopen. Anyone may also deposit as much money as they like. We still do not have any way of simulating the real-life experience of opening an account, because we must still execute two separate statements to open the account, as follows: Account myacct = new Account(); myacct.deposit(100); In addition, there is no way to set the account password. It is stuck at 29 forever. This means that any instance of the Account class will have this password. If you know the password on youracct, which is 29, then you also know the password on myacct, which is also 29. We can, of course, add a newpassword() method, which changes the password, but then we would have to execute three statements to open the account: a new statement to create the instance, a call to deposit to deposit some money, and a call to newpassword to change the password. The solution to this inefficient situation is the use of constructor methods. Constructor Methods. Constructor methods, or constructors as they are often called, are used to initialize instances. They are called when the new operator is used on a Java class. From your experience with JScript, this would seem to be the natural approach. In JScript, you call new on a function, and pass it arguments which become the properties and methods of that new instance. You use the special keyword this to denote the current instance. In Java, constructors are used

somewhat differently. For one thing, constructors are methods of the class itself. Constructors have two special aspects, as follows:
q q

The name of a constructor must be identical to the class name. A constructor has no return type.

The second aspect is the only case in which a method function does not have a return type. Other than these two special rules, a constructor is the same as any other method. Typically, you use a constructor to perform initialization, such as depositing money and setting the password to our Account class. Listing 10.5 shows the code for a constructor for Account which performs these two operations.

Listing 10.5 A Constructor for the Account Class


Account(int initdep, int newpword) { // Constructor declaration ivegot = initdep; // initialize amount on deposit password = newpword; // set new password isopen = true; // declare account open } // end of constructor This code must be inside the definition of the Account class, of course. This constructor meets both our requirements. It initializes the private variables ivegot and password with the two arguments to the constructor, and also sets the public instance variable isopen to true to declare to the world that the account is now open. We must now use the new operator with two integer arguments to create a new account: Account myacct = new Account(100, 12345); This statement creates an instance myacct of the Java class Account, with an initial deposit of 100 and a new password of 12345. There is still a problem with this class definition, because there is nothing stopping us from making the erroneous statement: Account badacct = new Account(-100, 12345); This creates a perfectly valid instance, named badacct, with an initial balance of -100. The result here is simply nonsensical, but, in other cases, spurious initialization can lead to disastrous results. There is, in fact, a way of providing error-checking by using the isopen instance variable. Listing 10.6 shows a modified version of the Account constructor, which checks the initial deposit and makes sure that it is at least 100.

Listing 10.6 A Constructor for the Account Class with Error-Checking


Account(int initdep, int newpword) { // Constructor if ( initdep >= 100 ) { // 2; minimum deposit requirement met

ivegot = initdep; password = newpword; isopen = true; } else // 7; minimum deposit requirement not met isopen = false; // 8; declare failure } This constructor tests the argument initdep, in statement 2, to make sure that it passes the minimum deposit test. If it does pass, the same three initialization statements of Listing 10.5 are executed. The constructor then sets the isopen variable to true to indicate that the instance was successfully constructed (line 6). If the initial deposit test failed, the code branches to line 8 instead. This statement ensures that isopen is set to false to indicate that the instance construction failed. Method Signatures in Java. At this point, our Account class has many of the features of a real bank account. We have password protection, all the methods that represent everyday transactions, and a reasonably accurate constructor. A little fine-tuning will give it even more verisimilitude, as well as illustrate one of the most important aspects of Java methods. In real life, many bank accounts are rarely this simple. Accounts often have several different pools of money (savings, checking, checking/NOW, CD) with different rules on how these pools must be handled. You might want to open a checking account and a savings account at the same time. We could accommodate this by rewriting the Account constructor to accept three arguments representing the initial savings deposit, the initial checking deposit, and the new password. If either of the two initial deposit amounts is zero, we would interpret this as meaning that no account of that type was to be opened. There is a simpler way, however. In Java, we can have more than one method with the same name, so long as all the argument lists are different. Suppose we assume that the default is to open only a checking account, and use the constructor shown in Listing 10.6 to perform that operation. We now need another constructor that will open both a checking and a savings account. Listing 10.7 shows this new constructor. Note that it references a new private instance variable named ivegotsav, which holds the savings account balance.

Listing 10.7 An Alternate Constructor for the Account Class


Account(int initdep, int initsdep, int newpword) { if ( initdep >= 100 && initsdep >= 1 ) { // min balance tests ivegot = initdep; // initialize checking ivegotsav = initsdep; // initialize savings password = pword; // reset password isopen = true; // accounts are open } else isopen = false; // below minima; don't open account }

The constructor of Listings 10.6 and 10.7 can both be used in the same class. Java tells them apart by virtue of the fact that their argument lists are different. The constructor of Listing 10.6 takes two int arguments, while that of Listing 10.7 takes three. This is often referred to as the method signature or the method shape, and is written as (int, int) or (int, int, int), respectively. The following statements open two new accounts (create two new instances of the Account class): Account myacct = new Account(100, 12345); Account wifesacct = new Account(500, 100, 54321); The instance myacct represents a checking account with an initial deposit of 100, and a password of 12345. The instance wifesacct has both a checking account and a savings account, with initial deposits of 500 and 100, respectively, and a password of 54321.

NOTE: Multiple class methods can have the same name so long as they have different method signatures. This technique is known as overloading. While overloading is most useful for constructors, because the name of the constructor is fixed by the name of the class, it can be used for any class method.

The static and final Keywords. Now that we have introduced the concept of two pools of money within an Account, we must obviously modify the deposit, balance, and withdraw methods to make them aware of this fact. Let us suppose that we can withdraw money only from the checking account, but we can deposit money to either account, and query either account's balance. It would be nice to give the deposit and balance methods a tag indicating which pool of money to use. If we were writing this code in C or C++ (or several other languages), we could make the tag be the member of an enumerated type. We could also use the #define construct to define symbolic constants to stand for the two types of account. Finally, we could create consts in C++ and use those for the two account types. How does one create a constant in Java? This question is answered as we dissect the code in Listing 10.8, which shows our final version of the Account class. This file is ex10_8.java on the CD-ROM.

Listing 10.8 ex10_8.java--A Fully Functional Version of the Account Class


class Account { // Account Class private int ivegot = 0; // 2; amount in checking account private int ivegotsav = 0; // 3; amount in savings account private int password = 29; // 4; account password public boolean isopen = false; // 5; account has money? // these constants refer to the checking and saving accounts public static final int CHECKING = 1; // 6; public static final int SAVINGS = 2; // 7; // all accts at this bank have this id

public static int Bankid = 2167; // 8; // Constructor: open checking acct only Account(int initdep, int newpword) { // 9; if ( initdep >= 100 ) { // 10; min deposit reqt met ivegot = initdep; // 11; init checking acct password = newpword; // 12; set acct password isopen = true; // 13; the acct is open } else // 15; minimum deposit requirement not met isopen = false; // 16; insure failure } // 17; end of first constructor // 3 argument constructor Account(int initdep, int initsdep, int newpword) { // 18; if ( initdep >= 100 && initsdep >= 1 ) { // 19; min balance? ivegot = initdep; // 20; initialize checking ivegotsav = initsdep; // 21; initialize savings password = pword; // 22; set password isopen = true; // 23; accounts are open } else isopen = false; // 26; below min; don't open } // 27; end of 3 arg constructor // deposit method: anyone can deposit anywhere ( no password ) void deposit(int n, int which) { // 28; if ( n <= 0 ) return; // 29; no negative deposits if ( which == Account.CHECKING ) // 30; to checking ivegot += n; // 31; deposit to checking else if ( which == Account.SAVINGS ) // 32; to savings ivegotsav += n; // 33; deposit to savings } // 34; end of deposit method // password protected balance method int balance(int pword, int which) { // 35; if ( pword != password ) // 36; incorrect password return( -1 ); // 37; return bogus balance // checking account balance wanted if ( which == Account.CHECKING ) // 38; return(ivegot); // 39; return it // savings account balance wanted else if ( which == Account.SAVINGS ) // 40; return(ivegotsav); // 41; return it else // 42; some strange `where' return( -2 ); // 43; return error code } // 44; end of balance method // password protected checking acct withdrawal boolean withdraw(int pword, int n) { // 45; if ( pword != password ) // 46; bad password

return(false); // 47; cannot withdraw if ( n > ivegot ) // 48; too much return(false); // 49; cannot withdraw ivegot -= n; // 50; update checking acct balance // update the isopen variable isopen = ( (ivegot+ivegotsav) > 0 ? true : false ); // 51; return(true); // 52; return status } // 53; end of withdraw method } // 54; end of Account class For the most part, this version of the Account class is an amalgamation of the two constructor methods we introduced in the previous sections, together with updated versions of the deposit, withdraw, and balance methods from Listing 10.4. This version does introduce two new keywords, static and final, and one new concept, that of a class variable. We will examine in detail how this class now works. There are seven variables declared in lines 2 through 8. The first four have already been introduced: ivegot and ivegotsav hold the checking and savings account balances, password holds the account password, and isopen is the overall account status. The only change we have made is to explicitly declare isopen to be public. These four variables are instance variables; the first three are also private. The next three statements (lines 6 through 8) use the new keywords, as follows: public static final int CHECKING = 1; // 6 public static final int SAVINGS = 2; // 7 public static int Bankid = 2167; // 8 The final keyword simply states that this value may never be altered. A final variable must be initialized. final in Java serves the same purpose as const does in C++. The static keyword has a different purpose. It indicates that all instances refer to exactly the same shared variable. The static keyword makes a variable a class variable rather than an instance variable.

TIP: Declare class constants to be both final and static.

To understand the difference between a class (static) variable and an instance variable, consider the difference between the instance variable ivegot and the class variable Bankid, which we have just invented to hold an identifier associated with all accounts at this particular bank. Every instance of the Account class will have its own copy of the instance variable ivegot. The amount of money in my account, represented by the myacct instance, is unrelated to the amount of money in your account, represented by the youracct instance. You can conduct thousands of transactions, and amass millions of dollars in the ivegot instance variable of youracct without it having any effect on the ivegot instance variable of myacct (unfortunately).

This is not the case with the class variable Bankid. There is exactly one such variable, and it is shared among all instances of the Account class. This is what makes it a class variable: It belongs to the class, and not to the individual instances of the class. This also means that we may refer to it as Account.Bankid, as well as myacct.Bankid and youracct.Bankid. Note that the static and final keywords may also be applied to methods. We have already seen examples of static methods in JScript, in the Date object. See the section, "The Date Object" in Chapter 5, "Built-In JScript Objects," for a complete description of its static methods and how they are used. The Account class has two constructors, which we have already seen. The two-argument constructor is given in lines 9 through 17. It creates a checking account only. The three-argument constructor, which allows us to open both checking and saving accounts simultaneously, is shown in lines 18 through 27. Both constructors check their arguments to ensure that minimum deposit requirements are met, and set isopen to false if they are not. We have rewritten the deposit method so that is takes a second mandatory argument, called which. This argument is used to indicate which account should receive the deposit of n. Errorchecking of n happens in statement 29, which refuses to make a deposit if the amount is negative, as follows: if ( n <= 0 ) return; // 29; negative deposit forbidden If the test passes, then the value of which is examined. It is expected to refer to one of the class constants CHECKING or SAVINGS. Note that we refer to them as Account.CHECKING and Account.SAVINGS, in statements 30 and 32. This is a class reference, which is permitted since they are static. We could just as well have used the instance references this.CHECKING and this.SAVINGS, since these constants are part of each instance, too. If this is a checking account deposit, then the test in statement 30 passes and n is added to the checking account instance variable ivegot in statement 31. If which is Account.SAVINGS instead, then n is added to ivegotsav in statement 33 as follows: if ( which == Account.CHECKING ) // 30; checking account deposit ivegot += n; // 31; deposit to checking else if ( which == Account.SAVINGS ) // 32; saving acct deposit ivegotsav += n; // 33; deposit to savings If which is not equal to either constant, nothing happens. We just fall off the end of the deposit method, which is quite acceptable since it is a void method. The code for the balance method, on lines 35 to 44, operates in the same way as the deposit method. It performs its usual password test (line 36). If that test passes, it tests the value of which and returns the corresponding balance. If which is neither CHECKING nor SAVINGS, the method returns an error code of -2. This value was deliberately chosen to be different from the bad password

error return of -1 on line 37. The caller can distinguish the two error cases based on which bogus balance was returned. The implementation of the withdraw method (lines 45 to 53) is almost unchanged from our previous version. We assume that we are permitted to withdraw only from the checking account, so no which parameter is needed. The test that updates the isopen variable has been updated to keep the account open so long as the total balance in both accounts (ivegot+ivegotsav) is greater than 0. This test is shown on line 51, as follows: isopen = ( (ivegot+ivegotsav) > 0 ? true : false ); // 51; open? Arrays in Java. There is one final piece of Java object machinery that we need before we can launch forward and actually make something appear on a Web page. We need Java arrays. It should come as absolutely no surprise that arrays are actually objects (classes) in Java. The similarity with JScript arrays ends there, however. There are no associative arrays in Java, and there are no extensible arrays. Java's usual strictness is carried to fanatic extremes in dealing with arrays. Java enforces the following five rules for all of its arrays:
q q q q q

Arrays must be created with the new operator or by explicit initialization. Every array has fixed length, given by its length instance variable. Every array element must have the same type. It is impossible to access memory before the beginning of an array. It is impossible to access memory beyond the end of an array.

This very restrictive approach is part of Java's security model. One of the most common ways of accessing memory that is not really yours is to declare an array, say int i[10], and then look at elements such as i[-6]. Veteran FORTRAN and C programmers will recognize this as the famous "stack creep" technique for reaching into system memory. Of course, arrays are also a source of completely innocent but vicious errors, such as referring to i[10], even though only i[0] through i[9] really belong to us.

TIP: Java arrays are zero-indexed, as in C, C++, and JScript.

Let us briefly consider how to use arrays in Java. If we actually do want an array of 10 ints, we must declare a variable to hold this array, and then allocate it using the new operator. The following statements do the trick: int iarr[]; // declare an int array variable iarr = new int[10]; // allocate space Before we call the new operator, the variable iarr is absolutely uninitialized, just as the statement

Account myacct; declares an instance myacct of the Account class, but does not actually create such an instance. It is absolutely prohibited to attempt to make an array declaration such as: int badiarr[10];// hopelessly bad, awful, and wrong The format used to allocate iarr is the pattern that should be followed to allocate an array of anything; do not attempt anything like the declaration of badiarr. In particular, we can use these two statements to allocate an array of Account instances: Account acctarr[]; acctarr = new Account[10]; The variable iarr represents an array of 10 ints, and the variable acctarr represents an array of 10 Account instances. None of these is initialized yet, however, so it is unwise to attempt to refer to iarr[5] or acctarr[3]. Each of the array slots must be initialized. Array creation is really a two-step process, in which the memory is first allocated using new, and the individual values are then set. We could say: acctarr[0] = myacct; acctarr[1] = youracct; acctarr[2] = new Account(2000, 14141); and so forth to fill in the various slots in the acctarr. We can also use explicit initialization, which creates an array and fills in its values at the same time. The following statement, for example, creates an array of four floating-point values: float fltarr[] = { 3.14159, 2.71828, 1.4141, 0.7071 }; In each of these cases, we may get the length of the array using the instance variable, so both iarr. length and acctarr.length are 10, while fltarr.length is 4. The valid elements of the array range from index 0 through index (length-1). An out-of-bounds error results if any other elements are accessed.

CAUTION: It is often worthwhile to check an array reference to make sure that it is in bounds. This can be accomplished using an if test against the length member, as follows: if ( 0 <= idx && idx < arr.length ) ok to use arr [idx];

The other grievous mistake in Java is to attempt to set an array element to any type other than its base type. Therefore, any member of iarr[] must be an int, any member of acctarr[] must be an instance of the Account class, and every member of fltarr must be a float. A statement such as

fltarr[2] = "pi" generates a Java exception.

Java Statements
So far, we have said very little about statements in Java. You have no doubt noticed that, in each of the previous listings, Java statements greatly resemble JScript statements. Java has a few extra rules, though, and also a few new statement types that are not supported in JScript. There are also some JScript constructions that cannot be done or can be done only very awkwardly in Java. The reader is strongly encouraged to review Chapter 2, "JScript: The Language," particularly the section on "Control Structures" and the discussion of "Operator Precedence." Because Java follows almost the same set of rules as JScript, we will not attempt an exhaustive discussion of those rules. Instead, we will focus on a few of the major differences. As mentioned quite early in this chapter, Java statements must be terminated with a semicolon. While this is a matter of style in JScript, it is mandatory in Java. If you omit the semicolons, Java attempts to interpret your program as a single gigantic statement, to your eternal embarrassment. It is already apparent that Java has the if statement; it also has the while and for statements of JScript. Java has three more very interesting control structures that are not present in JScript: the do...while statement, the switch statement, and a variant on the break and continue statements that takes a label. In compensation, Java does not have the for...in statement of JScript. The reason for this latter omission has to do with the more circumscribed way that Java defines objects, as we have just seen. The do...while Statement. The while statement in Java and the while statement in JScript are identical. Both evaluate their while clause and then execute the while body only if the conditional in the while clause was true. This means that the while body may be executed an infinite number of times, once, or not at all. If we were foolish enough to write: while ( false ) { find the meaning of life; } the while body would never be executed. The valid but meaningless while ( false ) would never be used in practice, of course, but it is quite possible to have a while clause that does evaluate to false immediately. This is unfortunate in cases where it is desirable to execute the while body at least once. The do...while statement solves this problem. A do...while statement still contains a while body and a while test, but the while test is at the end, ensuring that the body of the do...while loop is executed at least once. The format of this statement is as follows: do { while-body; } while ( conditional ) ;

CAUTION: The semicolon at the end of the while clause in a do...while statement is mandatory. The usual rule that the closing brace of a { } code body terminates the body does not apply to the do...while statement, because the while clause must occur after the closing brace.

The switch Statement. The switch case secondval: statement is used to select one alternative from a set of possible choices. It is designed to be a more compact form of the if... else construction, particularly in cases where there are many possibilities. The format of the switch statement is shown in Listing 10.9.

Listing 10.9 The Java switch Statement


switch ( numberthing ) { case firstval: statements; break; statements; break; ... default: statements; break; } Unlike the other conditional statements, the numberthing element inside the switch test is not a logical value, it is a numerical value. In particular, it must be a numerical value whose underlying type is byte, short, char, or int. The value of the numberthing is compared against each of numerical values in the case statements. Note that each case statement ends with a colon (:). This is mandatory. If it finds a match, it executes the statements after the case statement but before the first break statement. If none of the case clauses provides a match, it looks for a clause of the form: default: which matches anything that is not otherwise matched. In this situation, all the statements between the default and the next break statement are executed. As an example, consider the balance method in Listing 10.8. It does a three-way test on its argument which. This three-way test can be easily rewritten as a switch statement; the code is shown in Listing 10.10.

TIP: Default cases in switch statements are not required, but are recommended.

They often catch otherwise mysterious errors.

Listing 10.10 The Account.balance Method Rewritten Using the switch Statement
int balance(int pword, int which) { int retval; // 2; local variable for return if ( pword != password ) // 3; incorrect password return( -1 ); // 4; return bogus balance switch ( which ) { // 5; switch on the value of "which" case Account.CHECKING: // 6; which == Account.CHECKING retval = ivegot; // 7; checking balance break; // 8; done with checking case case Account.SAVINGS: // 9; which == Account.SAVINGS retval = ivegotsav; // 10; savings balance break; // 11; done with savings case default: // 12; which has any other value retval = (-2); // 13; return code indicates an error break; // 14; done with the default case } // 15; end of switch statement return(retval); // 16; return the return code } This version of the balance method performs the usual password test, and then immediately enters a switch, in statement 5. The numerical value being tested is which, which is an int. If the value of which is Account.CHECKING, then the case Account.CHECKING: statement at line 6 matches, and statement 7 is executed:

case Account.CHECKING:

// 6; which == Account.CHECKING

retval = ivegot;

// 7; return code is checking balance

break;

// 8; done with checking case

This assigns the checking account balance ivegot to the local variable retval. The break statement at line 8 is then executed. Like any good break statement, it directs the flow of control to the first statement after the switch, namely statement 16, which returns retval. If which has the other valid value Account.SAVINGS, a similar block of code is executed, which gives retval the value of the savings account balance ivegotsav instead (lines 10 and 11). If which has any value other than Account.CHECKING or Account.SAVINGS, then the default case, at line 12, matches and statements 13 and 14 execute, as follows:

default:

// 12; which has any other value

retval = (-2);

// 13; return code indicates an error

break;

// 14; done with the default case

In any case, the code ends up at line 16 with retval having one of the two valid values, ivegot or ivegotsav, or the error value -2. In a situation such as this, where there are only three possible alternatives, the amount of code saved by using a switch statement versus multiple if...else statements is minimal. If there had been a few more alternatives, the savings would have been dramatic, however.

Troubleshooting I have a very simple switch statement that examines an integer variable i. Based on the value of i, it sets a local variable j. For some reason, the two cases i==1 and i==2 always give the same result, even though they have different code in their case blocks. What is wrong? The code looks like this: switch ( i ) { case 1: j = 2*i; case 2: j = 3*i; break; ...

} You have made the most common error in using a switch statement. There is no break statement to conclude case 1. When i is equal to 2, the statement j = 3*i is executed, and j gets the value 6, as it should. However, when i is equal to 1, the statement j = 2*i is executed, and then the statement j = 3*i is also executed, so that j has the incorrect value 3 rather than the correct value 2.

The switch statement is more than happy to execute multiple blocks of code. The only way it knows to stop is when it encounters a break statement. The presence of another case statement, as you have included, won't even slow it down. This is known as "falling through" a case statement. Sometimes this is desirable, but usually it is just an error. The Labeled break and continue Statements. With the if, while, for, and the new switch statement, Java has a rich collection of techniques for controlling statement execution. Java also has one more trick up its sleeve, which can prove very valuable in cases where there are many nested conditionals. It might seem like overkill to add more and more new control structures, since this often leads to confusion. There is a school of thought that says everything can, and should, be reduced to just a single type control, such as while. This may be accurate in a purely theoretical sense, but it often is impractical. On the other hand, it is also true that multiple control structures, particularly nested ones, can be hard to manage. If you have a for inside an if inside a while, and you say break, where do you go? You certainly know by now that the correct answer is that the break sends you to the first statement after the while block, wherever that is. This may be the correct answer, but it is often not the answer you want. If some kind of error or exceptional condition occurs, or if you have finally completed a calculation, you might want just to exit completely from the for, if, and while blocks. This is a situation in which many long for a goto statement. Java does not have a goto statement. It does have a mechanism for going to an arbitrary location when a break or continue statement is executed. This is known as the labeled break or labeled continue statement, because the keyword is followed by a label that indicates the desired destination. Listing 10.11 shows a very peculiar set of Java code that illustrates the labeled break.

Listing 10.11 Using the Labeled break in Java


int i, j, k, w; outtahere: // 2; label for(i=0;i<200;i++) { if ( i%3 == 0 ) { j = 7*i; k = 0; while ( k++ < j ) { if ( k == 29 ) // eureka! break outtahere; // 8; this gets us out of here } // end of while } // end of if

} // end of for w = j; // 12; this is where you will actually end up Note that the label outtahere must come before the outermost loop, at statement 2. When the labeled break of statement 8 is executed, control actually flows to the first statement after the outermost (for) block, at statement 12 (which is w = j; in this example). This counterintuitive structure is necessary since the label must occur before any statement that uses it. Note also that the label must end with a colon (:). Think of the label outtahere as a name for the next statement, which is the entire mass of the for statement in this case. A labeled break goes to the first statement after the labeled statement, while a labeled continue goes back to the labeled statement. If statement 8 had said continue outtahere, then the mathematical madness of Listing 10.11 would be started all over again.

Developing Java Applets


We have now learned a considerable amount about the Java language itself. The next topic to consider is how it can be used on a Web page. The answer is surprisingly different from the JScript approach. Writing JScript is almost like writing HTML. You fire up your favorite text editor or HTML Wizard, create JScript event handlers and utility functions, link them to events on a Web page, and you are done. When you load the page, the JScript is executed when events arrive. Java is fundamentally different. JScript is (almost) always interpreted, meaning that the Web browser analyzes the text content of the JScript code on-the-fly, as it is needed. Java, on the other hand, is a compiled language. Java source is never included directly ma Web page. Instead, a special APPLET tag is used to reference Java code in a special binary format.

The Java Development Cycle


Java is actually both compiled and interpreted, as contradictory as that seems. To understand how this is possible, we must examine the process used to develop Java code. The first step, of course, is to write Java source code. We have already seen a substantial amount of Java source in the various listings in this chapter. If we were writing JScript, we would now be almost done, because we could embed the code directly on a Web page. With Java, we must first convert the source in a binary format, known as Java bytecodes. One of the fundamental principles of Java is that it is architecture neutral: It can run on any type of machine with a Java-capable Web browser. This goal could not be met if Java were compiled into Intel 486 binaries, or Sparc-5 binaries, or any specific machine's binary format. Instead, Java is compiled into the binary format for an abstract (or virtual) machine. For quite a while, this virtual machine did not have a physical counterpart--it was simply an abstract instruction set. In March 1996, however, Sun Microsystems announced that it would begin construction on a set of "Java microprocessors," which will actually run the Java instruction set directly. Every other machine must still translate the Java instructions into its own native instructions, however.

When we write Java, we must therefore perform three steps, as follows:


q q q

Create the Java source code. Convert the Java source code to the abstract binary format. Reference the Java binary code on a Web page.

The second step of this process requires that we use a Java compiler to create Java binary code. There are several compilers available; the simplest, and one of the most widely used, is part of a set of tools from Sun known as the Java Development Kit (JDK). The third step makes use of the APPLET HTML tag. These two steps are discussed in the next two sections. First, the question of why Java is both interpreted and compiled is still open. The answer is that we, the Java programmers, compile Java into its abstract binary format, but the Web browsers must then interpret that format. When a Web browser accesses a page that contains an APPLET tag specifying Java code, the Web browser fetches the binary version of that code (not the Java source). The Web browser must then interpret those abstract instructions to do real work on a real machine. After all, if you have Internet Explorer running under Windows 95 on a Pentium, and IE tries to hand the Java bytecodes to the Pentium chip, the Pentium chip will spurn them.

Java Compilers and the JDK


The Java Development Kit, or JDK, is a simple set of command-line-driven tools for manipulating Java source and binary files. The JDK was the first such set of tools, but is not the only such set. In fact, there are now many sophisticated graphical development environments for Java. Because the JDK is the simplest and still one of the most widely used Java development environments, this section describes it in some detail. It is also important to realize that there are several different versions of the JDK. The Macintosh version of the JDK has no command-line interface, for example. It is beyond the scope of this book to provide a comprehensive description of all the tools in the JDK, or to discuss the differences between the various versions. However, we will at least mention all its major components, which are as follows:
q q q q q q q

appletviewer java javac javadoc javah javap jdb

If you use the JDK, the appletviewer and javac tools are the two you will use the most often, at least at the beginning of your Java career. The appletviewer is an application that can be used to view Java applets outside of any Web browser. Usually, you write a Java applet, compile it using the Java compiler javac, and then test it using the appletviewer. The appletviewer frees

you from having to debug both your HTML and your Java code at the same time. It is also useful in tracking down browser-dependent bugs, since appletviewer is not itself a browser. The appletviewer and the Java compiler javac are available on all platforms supported by the JDK. The JDK can be downloaded free from Sun Microsystems' site at http://www.javasoft.com. The JDK is available for many popular platforms, including Windows 95, Windows NT, Solaris 2.4 and 2.5, Linux and several other versions of UNIX, and the Macintosh. This list will no doubt continue to grow, so you are advised to check the javasoft Web site regularly for the latest information. Components of the JDK. The unfortunately named java application is a Java interpreter. If you give the java application a Java binary file, it executes the contents of that file. This application is not really of interest to us, since it is primarily used to test and execute stand-alone Java applications rather than applets. Java is a large enough language that it is possible to write full-blown applications in Java. java is then used to execute them. The javadoc application automatically generates HTML documentation from Java source code. It looks for specially formatted comments with the source, and uses those to construct the corresponding documentation. We will see a few simple examples of such comments in the next chapter. The javah application is used when you want to mix Java code with C or C++ code. javah generates .h include files that allow Java, C, and C++ to interoperate. At the moment, Java applets are forbidden from using modules written in any language other than Java (known as native methods), so javah is not of interest to us. Java enforces this prohibition for security reasons. javap is the Java profiler. It allows you to instrument Java code to discover which portions of it are taking the most time. jdb is the Java debugger. It permits symbolic debugging of Java binaries. Once you are a bit further along the Java learning curve, you may well want to explore these tools further. The Java Compiler. The javac tool is the Java compiler. It is invoked by giving it the name of one or more Java source files. If the files contain valid Java, they will be converted to the binary format of the Java instruction set. Let us take the source code of Listing 10.8, contained in the file ex10_8.java on the CD-ROM, and make a very tiny change--modify the class declaration to say public class Account instead of class Account. If we do this and then attempt to compile it using the following statement: javac ex10_8.java the Java compiler complains, with a message saying that the public class Account must be defined in a file called `Account.java'. Well, if it must, then it must. If we oblige and rename the file to Account.java (which can also be found on the CD-ROM), and then try: javac Account.java It succeeds, and the file Account.class is created. Files with the suffix .class are Java binary files. This seemingly peculiar restriction on the file name of the source code for a public class is

something that must simply be tolerated in this revision of the JDK. In addition, we must make the Account class be a public class if we wish to refer to it in other files. Finally, there is no flexibility in the name of the binary output file, either. The compiled version of the public Account class must be contained in a file named Account.class. The underlying reasons for these file name restrictions are complex, and cannot really be explained without a long and painful discussion of Java internals. For our purposes, we will simply accept these rules, which are summarized in the Note that follows. NOTE: Public classes in Java should follow these rules: Put only one public class definition in a Java source file. The name of the source file must match the name of the public class. Do not rename the compiled output file. It must be the name of the public class, followed by the suffix .class.

Other Java Development Environments. For a long time, the JDK was the only game in town. Because Java was developed by Sun, it is only natural to expect that Sun's development environment would be the first and also the most comprehensive. Because of Java's explosive popularity, though, a number of other environments have been created. Some are free, like the JDK, while others are commercial products. One effect of Java's overwhelming growth rate is that any list or description of Java tools would be hopelessly out of date before it could be printed. No attempt will be made to present such a list in this book. Instead, the best way to learn about such tools is on the Web itself. There are two resources that can be used to obtain the most up-to-date information. The Gamelan repository, at http://www.gamelan.com, contains a very large collection of information about Java, JScript, and many other Web-related topics. The Gamelan site boasts several hundred Java entries. Some are simple applet demonstrations, while others are full-blown development tools. Both commercial offerings and public domain code are represented. The Java page is well worth visiting. After some initial reluctance, Microsoft (http://www.microsoft.com) has also entered the Java arena. Its Java development environment is intended to be fully integrated with the Microsoft philosophy toward software products. This means that it has a visual development environment, similar to Visual Basic and Visual C++. It is also designed to interface smoothly with Microsoft's object system (known as COM and DCOM). One of the most interesting features that Microsoft supports is the ability to compile Java directly to native machine code, in addition to producing standard .class output files. Of course, the native code will not be platform-independent, but significant performance improvements are obtained. If you will be developing Java on any of the Windows platforms, you should plan on regular visits to Microsoft's Web page for the latest information.

The APPLET Tag


Now that we have a compiled Java file, we are at last approaching the point at which we can actually

create a fully functional Java applet. Since Java applets are binary files, there is no way we can literally include them in HTML, as we did using the <SCRIPT>... </SCRIPT> block for JScript. Instead, we must use a new HTML tag, the APPLET tag, to reference the Java binaries for our applet. An APPLET block consists of the following four parts:
q q q q

The <APPLET> declaration itself A set of parameters that may be given to the applet using the PARAM tag Alternate text The closing </APPLET>

An example showing the basic HTML syntax for an APPLET block is shown in Listing 10.12.

Listing 10.12 Example of an APPLET Block in HTML


<APPLET CODE="Something.class" WIDTH=100 HEIGHT=50> <PARAM NAME="var1" VALUE="5"> <PARAM NAME="othervar" VALUE="somestring"> This alternate text is displayed on Java-impaired browsers </APPLET> Mandatory Attributes. The example in Listing 10.12 attempts to load and execute the Java binary code from a file named Something.class given as the value of the mandatory CODE attribute. By default, a Java-capable browser searches for files referenced by CODE relative to the HTML document's BASE, although this search strategy can be changed by the optional attribute CODEBASE, described in the next section. The mandatory WIDTH and HEIGHT describe the size of the box that is allocated for this applet. The applet may later attempt to change this size itself. The values of the WIDTH and HEIGHT attributes are in pixels. On a Java-enabled browser such as Internet Explorer, the example of Listing 10.12 is drawn inside a box of 100x50 pixels. Other browsers display the alternative text instead. This alternative text is displayed by Java-impaired browsers. The alignment of the applet's bounding box may be influenced by the optional ALIGN attribute.

TIP: APPLET tags may be enclosed in a heading (<Hn>), paragraph (<P>), or division (<DIV>) block, or some other block delimiter.

Optional Attributes. The APPLET tag also accepts the following optional attributes:
q q q q

ALIGN CODEBASE HSPACE NAME

VSPACE

The ALIGN attribute is used to specify the alignment of the applet's bounding box with respect to other adjacent text and graphics. The values of the ALIGN attribute include BOTTOM, MIDDLE, and TOP, much like the IMG tag. They also include an additional set including ABSBOTTOM, ABSMIDDLE, BASELINE, LEFT, RIGHT, and TEXTTOP for more precise control. The CODEBASE attribute is used to specify an alternative location at which to find the Java binary specified in the CODE attribute. If the value of the CODEBASE attribute is an absolute path, then that path is searched for the Java code. If CODEBASE is specified as a relative path, such as java \classes, then that path is appended to the document's BASE, and the code is sought in that relative location. This is often useful if you want to keep your HTML in one place, and your java binaries in another. HSPACE and VSPACE are used to define the amount of horizontal and vertical space that should be created as a border for the applet. Both specify a numerical value in pixels. The NAME attribute is used to give the applet a name, which may be completely unrelated to any of the names of the classes it uses. Applet NAMEs are used for applet-to-applet communication, and also reserve a place for the applet in the JScript HTML hierarchy.

NOTE: The APPLET tag does not currently accept an ALT attribute to specify alternate text for Java- impaired browsers. Such text must be embedded in the <APPLET>...</APPLET> block itself.

The PARAM Tag. The <APPLET>...</APPLET> block may contain any number of PARAM tags. Each PARAM tag takes two attributes: NAME and VALUE. The value of each of these attributes is an uninterpreted string. This is the standard mechanism for passing in initialization parameters from the Web page to a Java applet. Java applets have a special method, called getParameter(), to retrieve such values from their environment. Note that each PARAM tag specifies exactly one parameter.

A Simple Applet
We are now ready to construct a simple Java applet. This applet doesn't do much. In fact, all it does is display a string in color. We will arrange to pass in a string to be displayed using a PARAM tag. This applet shows us most of the fundamental components of Java applet design. The HTML code for a page containing the applet is shown in Listing 10.13, while the code for the applet itself is shown in Listing 10.14. These files are ex10_13.htm and pstr.java, respectively, on the CD-ROM.

Listing 10.13 ex10_13.htm--A Web Page Containing a Simple Applet


<HTML>

<HEAD> <TITLE>Displaying a String in Java</TITLE> </HEAD> <BODY> <P> <HR> <APPLET CODE="PStr.class" WIDTH=400 HEIGHT=40 ALIGN="CENTER"> <PARAM NAME="mystring" VALUE="coconuts"> You will see this text if your browser does not understand Java. </APPLET> <HR> The <A HREF="PStr.java">source</A> </P> </BODY> </HTML>

Listing 10.14 PStr.java--A Java Applet that Displays a String


import java.lang.* ; // 1; get Java language package import java.awt.* ; // 2; get Java AWT package public class PStr extends java.applet.Applet { // 3; define applet type String userstring = null; // 4; instance variable public void init() { // 5; called when applet is loaded // get value of PARAM NAME="mystring" userstring = getParameter("mystring"); // 6; } // override built-in paint() public void paint( Graphics g ) { // 8; String outstr; // string concatentation outstr = "I've got a lovely bunch of " + userstring; // 10; g.setColor(Color.red); // 11; set output color to red // draw the string offset from the corner g.drawString(outstr, 10, 10); // 12; } } The code in Listing 10.13 should be self-explanatory. An APPLET is declared to be implemented by the CODE at URL PStr.class, relative to the document's BASE. Its dimensions are 100x40 pixels, and its alignment is CENTER. Some alternative text has been provided after the single PARAM tag, which gives the parameter mystring the value coconuts. A pointer is given to the source PStr. java in an HREF at the end of the <BODY>.

To run this applet, we must create the file PStr.class from the file PStr.java, which is shown in Listing 10.14. This is done using the javac tool, with the command: javac PStr.java This command creates the java binary PStr.class. We can now view the results by pointing our favorite Java-capable browser at the file EX10_13.HTML, or by invoking the appletviewer on it using the command appletviewer ex10_13.html. The results of viewing this HTML in Internet Explorer are shown in Figure 10.1. Figure 10.1 Java applets allow you to create text and graphics on-the-fly.

Anatomy of an Applet
Just how does the PStr applet work? The code in Listing 10.14 contains a number of new concepts that we describe next. The PStr applet begins with two new statements using the import directive, as follows: import java.lang.*; import java.awt.*; This directive is used to inform the Java compiler that externally defined classes may be needed. Statement 1 says to import java.lang.* ;, where the * is a wildcard indicating all the classes within the package java.lang. A package is a related collection of classes. Of course, this applet does not use all the classes in the java.lang package, but it does not hurt to overspecify when using an import statement. Only those elements that are actually needed are used. Statement 2 makes a similar request for the java.awt package. The AWT is Java's Abstract Windowing Toolkit, a collection of graphic utilities. Chapter 11, "More About Java," describes the class in the AWT and shows how several of them are used to load and manage images. Statement 3 declares the applet's class PStr. As indicated previously, this class name should be the same as the name of the file in which it is found. Rather than being a simple class declaration, however, statement 3 introduces one more new keyword, extends, as follows: public class PStr extends java.applet.Applet { Java supports the object-oriented notion of inheritance. This means that classes may be built on other classes, and inherit some of their properties and methods. In this case, the built-in applet class java. applet.Applet is being used as the base class (or superclass), and our customization PStr is the

derived class (or subclass). This frees us from having to write a lot of code, which would only duplicate the standard behavior of java.applet.Applet. All applets begin with a declaration of the form: public class Myclass extents java.applet.Applet { The PStr class contains a single instance variable, userstring, declared in statement 4. This variable is of type String, the Java string class. It also contains two methods, init(),and paint (). The init()method is one of four standard methods that are called during the life of an applet. The init method is called when an applet is first loaded, and should be used to perform any onetime initialization. The start method is called when an applet begins running, generally right after init completes. The stop and destroy methods are called when an applet is stopped (when another page is visited, for example), and when the browser is completely finished with an applet (when it falls off the end of the browser's cache, for example). This particular applet does not need to do anything when it is started, stopped, or destroyed, so these methods are not provided. In fact, the default java.applet.Applet class provides implementations of all of these methods, so that an applet need not actually provide any of them. The PStr class overrides the init method of its parent java.applet.Applet. A method is overridden when a subclass implements a method that is also implemented in its superclass. When this happens, the method in the subclass is used. Thus, the PStr class uses the superclass implementations of start, stop, and destroy and its own implementation of init. When the PStr.class file is loaded, the first thing that happens is that the init method is called. The init method executes a single statement (at line 6), as follows: userstring = getParameter("mystring"); which uses the Java function getParameter(). This function is used to retrieve the value of a PARAM tag whose name is given as an argument. Therefore, if there is a PARAM whose NAME attribute is mystring, the getParameter() call in statement 6 returns the VALUE of that PARAM. If not, it returns null. In our HTML code of Listing 10.13, there is such a parameter and its VALUE is the string coconuts.

NOTE: PARAM values are always interpreted as strings in Java.

The initialization is now complete, and the method function start from the applet superclass is called next. This method performs a variety of actions which need not concern us here. The most important thing it does from our perspective is that it will eventually arrange to call the paint method, which forces the entire drawing area of the applet to be redrawn. In particular, it forces a call to our paint() method, which this PStr has also overridden. Unlike the init method, which has a void signature, the paint method accepts a single argument, g, which is an instance of the

Graphics class. The methods of the Graphics class are used actually to do graphics. The paint method looks like the following: String outstr; outstr = "I've got a lovely bunch of " + userstring; // 10g.setColor (Color.red); // 11 g.drawString(outstr, 10, 10); // 12 Statement 10 constructs the output string outstr by concatenating a constant string with the value of userstring. Note that if userstring had been null, the value of outstr would be the string I've got a lovely bunch of null, since the quantity null is converted to the string null. Statement 11 sets the drawing color to red by using the red (static, final) class variable of the Color class. Finally, statement 12 draws the string outstr in that color. We place the string at relative coordinates (10,10), meaning that the string is offset 10 pixels from the top edge and 10 pixels from the left side of the applet's bounding box. Even though this applet is extremely simple, it does illustrate all the major aspects of applet design. The more complex applet described in the next section has the same basic components, as do the applets in Chapter 11, "More About Java."

An Accounting Applet in Java


In this section, we examine a slightly more sophisticated Java applet. This applet exercises the Account class that we have meticulously built up in the previous sections of this chapter. Our Java applet uses the PARAM tag mechanism to process a set of transactions. When it is done, it displays an account status in its applet window. The PARAM mechanism we use is extremely simple. We specify the number of transactions using a PARAM whose NAME is ntrans. The VALUE of this parameter is the total number of transaction parameters to follow. Each one of those PARAMs has a name of the form trans# followed by a number. Thus, the first transaction has PARAM NAME="trans#", the second NAME="trans#2", and so forth. The VALUEs of these transaction parameters encode what we want. If the value is of the form deposit:100, that indicates a deposit of 100, while if it is of the form withdraw:150, that indicates a withdrawal of 150. The Java source for this applet is shown in Listing 10.15. The source code for this applet can be found in the CD-ROM file Acex.java.

Listing 10.15 Acex.java--A Java Applet that Processes Account Transactions


import java.lang.* ; import java.awt.* ; public class Acex extends java.applet.Applet { // 3; class int ntrans = 0; // 4; number of transactions requested

int ntransdone = 0; // 5; number of transactions done int ndeposits = 0; // 6; number of deposits done int nwithdrawals = 0; // 7; number of withdrawals done int noverdrafts = 0; // 8; number of overdrafts private Account myacct = null; // 9; Account instance itself private static final int MyPass = 1492; // 10; secret password // private method to do 1 transaction private void do1trans(String thetrans) { // 11; String numpart; // 12; numerical part of a transaction int wherecolon; // 13; location of colon separator int valu; // 14; transaction' value int len; // 15; length of string boolean ok; // 16; withdrew ok? wherecolon = thetrans.indexOf(":"); // 17; find the sep if ( wherecolon <= 0 ) return; // 18; bad transaction len = thetrans.length(); // 19; overall length // get numerical part numpart = thetrans.substring(wherecolon+1, len); // 20; valu = Integer.parseInt(numpart); // 21; convert to int if ( valu <= 0 ) return; // 22; bad transaction switch ( thetrans.charAt(0) ) { // 23; trans type? // deposit ( 100 = numerical value of "d" ) case 100: // 24; myacct.deposit(valu, Account.CHECKING); // 25; ndeposits++; // 26; update counters ntransdone++; break; case 119: // 29; withdrawal ( 119 = "w" ) ok = myacct.withdraw(MyPass, valu); // 30; if ( ok == true ) { // 31; success nwithdrawals++, ntransdone++; // 32; } else { // 33; failure noverdrafts++; // 34; overdraft } break; } // 37; end of switch } // 38; end of do1trans() method public void init() { // 39; init method String tmp; String onetrans; int i; myacct = new Account(1000, 100, MyPass); // 43; tmp = getParameter("ntrans"); // 44; get # of trans

// if not null then convert to integer and set ntrans if ( tmp != null ) // 45; ntrans = Integer.parseInt(tmp); // 46; for(i=1;i<=ntrans;i++) { // 47; for all trans // try to find the parameter onetrans = getParameter("trans#" + i); // 48; if ( onetrans != null ) // 49; if found then.. do1trans(onetrans); // 50; do it } } // 52; end of init() public void paint( Graphics g ) { // 53; paint method String msg1, msg2, msg3, msg4; // 54; temp strings for messages int thebalance; // 55; final balance int loc = 15; // 56; drawing location thebalance = myacct.balance(MyPass, Account.CHECKING); // msg1 contains a report on number of transactions requested and performed msg1 = "Transactions requested: " + ntrans; msg1 += "; transactions performed: " + ntransdone; // msg2 contains a report on number of deposits and withdrawals done msg2 = "Deposits: " + ndeposits; msg2 += "; withdrawals: " + nwithdrawals; g.setColor(Color.black); // 62; draw it in black g.drawString(msg1, 10, loc); // 63; first message loc += 15; // 64; update y g.drawString(msg2, 10, loc); // 65; second message loc += 15; // 66; update y again if ( noverdrafts > 0 ) { // 67; oops, overdrafts... msg3 = "Overdrafts: " + noverdrafts; // 68; g.setColor(Color.red); // 69; draw it in panicky red g.drawString(10, loc); // 70; overdraft message loc += 15; // 71; update y } msg4 = "Balance: " + thebalance; // 73; balance message // If the balance is nonzero then draw it in green, otherwise red g.setColor(thebalance > 0 ? Color.green : Color.red); g.drawString(msg4, 10, loc); // 75; balance message } // 76; end of paint } // 77; end of Acex

The init Method


To understand how this applet works, let us approach it from a functional point of view. We know that the first thing in this applet that is executed is its init() method, which begins on line 39. The

following extract shows the first part of the init() method: String tmp; String onetrans; int i; myacct = new Account(1000, 100, MyPass); // 43; fire up account tmp = getParameter("ntrans"); // 44; get # of transactions // if not null then convert to integer and set ntrans if ( tmp != null ) // 45; ntrans = Integer.parseInt(tmp); // 46; The first thing the init method does is to initialize our Account instance, myacct, with starting balances of 1000 in checking and 100 in savings. It also sets the account password to the private variable MyPass. This illustrates one very important point about Java. The Account class is referenced indirectly, through its Account constructor. It is not necessary for us to include the Account class code. When the Acex applet is loaded and the init method is called, the Java interpreter within the browser detects that there is a reference to an external class on line 43. It knows that the name of that class must be the same as the name of the constructor. This tells it that it must load the file Account.class actually to call the Account constructor. This works, however, only now that we have made the Account class be public. This is the reason that we may not put the binary Java code for the Account class in a file named kickme.class, or in any file other than Account.class. If we do, the Java interpreter will not be able to find the class code. Even though the Java language has static binding, it also has dynamic loading. This keeps Java binary files as small as possible, since external classes are loaded only when they are needed. This is very desirable, since those binary files are being accessed across a potentially very slow network. After the Account class code has been implicitly loaded and the constructor called, the init method then calls the getParameter() function to retrieve the number of transactions, from the parameter "ntrans". If it can find such a parameter, it then attempts to convert that String value into an integer, on line 44. It uses the parseInt method of the Integer class, which has exactly the same purpose as JScript's built-in function of the same name. Once the init method has completed the initialization of the new Account instance and gotten the number of transactions, it then executes a for loop, beginning on line 47. This code is as follows: for(i=1;i<=ntrans;i++) { // 47; for all transactions // try to find the parameter onetrans = getParameter("trans#" + i); // 48; if ( onetrans != null ) // 49; if found then.. do1trans(onetrans); // 50; do it }

It iterates for the number of transactions requested. For each iteration, an attempt is made to find a parameter whose NAME begins with trans#. These parameters contain the transaction requests as their VALUEs. If a parameter of this type is found, the init method makes a call to the private method do1trans() to actually process the transaction.

The do1trans Method


The do1trans method is the workhorse for transaction processing. It accepts a String argument that contains the requested transaction in the form request:amount. To process such a request, it must separate the request type (deposit or withdraw), which occurs before the colon (:), from the request amount, which occurs after the colon. Let's examine exactly how this works on a request such as "deposit:400." The first few lines of the do1trans() method handle this type of parsing, as follows: wherecolon = thetrans.indexOf(":"); // 17; find the separator if ( wherecolon <= 0 ) return; // 18; bad transaction len = thetrans.length(); // 19; overall length of string // get numerical part numpart = thetrans.substring(wherecolon+1, len); // 20; valu = Integer.parseInt(numpart); // 21; convert it to an int if ( valu <= 0 ) return; // 22; bad transaction In line 17, a call is made to the String method indexOf. This call attempts to find the character index of the colon separator. In our case, that separator is the eighth character, so this method call returns 7 (since character indexing is zero-based). Line 20 uses the String method substring to extract the portion of the transaction string beginning at character index 8 to the end of the string. This is just the string 400 in our case, which, of course, corresponds to the numerical part of the transaction. The result is saved in the local String variable numpart. Line 21 uses the parseInt method again to convert this value from a String to an integer. The next block of code in the do1trans() method is used actually to process the transaction, as follows: switch ( thetrans.charAt(0) ) { // 23; type of transaction? // deposit ( 100 = numerical value of "d" ) case 100: // 24; myacct.deposit(valu, Account.CHECKING); // 25; do it ndeposits++; // 26; update counters ntransdone++; break; case 119: // 29; withdrawal ( 119 = "w" ) ok = myacct.withdraw(MyPass, valu); // 30; if ( ok == true ) { // 31; success; update counters nwithdrawals++, ntransdone++; // 32; } else { // 33; failure noverdrafts++; // 34; flag an overdraft }

break; } // 37; end of switch The switch statement on line 23 now examines the first character of the transaction string thetrans using the String method charAt. This method returns numerical values, so that we must use the numerical codes for the characters "d" and "w" in the case statements. If the first character is "d" (line 24), then this must be a deposit transaction. Line 25 carries out the transaction, and lines 26 and 27 update the counting variables ndeposits and ntransdone, which record the number of deposits and successful transactions, respectively. If the first character is "w" (line 29), then this is a withdrawal. We know that withdrawals may fail, so we record the result of calling the withdraw method of the Account class in the local variable ok on line 31. If the withdrawal succeeds, we again update counting variables (line 32). If it fails, we update a different counting variable, noverdrafts, which records the number of attempted overdrafts. Note that the do1trans method ignores any invalid input. If the input string was deposit:xxx or gag:45, both would be silently rejected. The former would fail the test on line 22, since xxx cannot be successfully parsed as an integer. The latter would simply fall off the end of the switch statement, since the first letter "g" matches neither "d" nor "w." Note also that the do1trans() also accepts a string of the form deltatron:200 as a deposit request (in the amount of 200), since it examines only the first character of the input. Most of the real syntax checking on deposits and withdrawals that you would find in a genuine accounting package has been eliminated from this example. This was done because the goal of this chapter is to introduce you to Java, not teach you about string parsing or bring you up to date on modern accounting practices. A fully robust version of the do1trans() method would have been many times longer, without any significant new Java content.

The paint Method


Once the init method has been executed, the applet's start method will be called. Once again, the Acex class does not provide its own start method, so that the default applet start method is called. This default start method will attempt to repaint the applet's drawing area, which will ultimately call our paint method. The paint method draws a series of strings in various colors summarizing the transactions. The following is the body of the paint method: thebalance = myacct.balance(MyPass, Account.CHECKING); // 57; msg1 = "Transactions requested: " + ntrans; msg1 += "; transactions performed: " + ntransdone; msg2 = "Deposits: " + ndeposits; msg2 += "; withdrawals: " + nwithdrawals; g.setColor(Color.black); // 62; draw it in neutral black g.drawString(msg1, 10, loc); // 63; first message loc += 15; // 64; update y coordinate

g.drawString(msg2, 10, loc); // 65; second message loc += 15; // 66; update y again if ( noverdrafts > 0 ) { // 67; oops, overdrafts... msg3 = "Overdrafts: " + noverdrafts; // 68; report how many g.setColor(Color.red); // 69; draw it in panicky red g.drawString(10, loc); // 70; overdraft message loc += 15; // 71; update y } msg4 = "Balance: " + thebalance; // 73; balance message g.setColor(thebalance > 0 ? Color.green : Color.red); // 74 g.drawString(msg4, 10, loc); // 75; balance message It gets the current account balance (line 57), and then constructs two strings recording the number of transactions requested, the number actually processed, and the total number of deposits and withdrawals (lines 58 to 61). It displays these strings in basic black (lines 62 to 66). Note that the xcoordinate of the strings is the same--it is always 10--while the y-coordinate, stored in the variable loc, is incremented after each call to drawString. This ensures that the strings are not drawn on top of one another. Having displayed this basic information, it next checks to see whether any overdrafts occurred, on line 67. If they did, it constructs a message indicating how many (line 68), sets the drawing color to red (line 69), and then draws that string (line 70). It also updates the y-coordinate for the next draw on line 71. Finally, the current balance is displayed. The color this string uses is determined by comparing the balance to 0. If the balance is greater than 0, green is used, while if it is 0, red is used (line 74). The final balance string is drawn in line 75.

Executing the Account Example Applet


To execute this Java applet, we must do two things: We must compile it and place the code in the appropriate directory, and we must also create some appropriate HTML that invokes it. The applet is compiled using the command: javac Acex.java which creates the binary file Acex.class. This must be placed in the same directory with the binary Account.class file, because that file needs to be loaded to resolve the various references to methods in the Account class. Finally, we must have a small piece of HTML that issues some transactions. This is shown in Listing 10.16 (the CD-ROM file is ex10_16.html). The result of browsing this tiny Web page is shown in Figure 10.2.

Listing 10.16 ex10_16.html--Executing the Accounting Applet on a Web Page


<HTML> <HEAD>

<TITLE>Using the Accounting Applet</TITLE> </HEAD> <BODY> <P> <HR> <APPLET CODE="Acex.class" WIDTH=400 HEIGHT=400 ALIGN="CENTER"> <PARAM NAME="ntrans" VALUE="5"> <PARAM NAME="trans#1" VALUE="withdraw:400"> <PARAM NAME="trans#2" VALUE="deposit:10"> <PARAM NAME="trans#3" VALUE="withdraw:900"> <PARAM NAME="trans#4" VALUE="withdraw:330"> <PARAM NAME="trans#5" VALUE="deposit:250"> You will see this text if your browser does not understand Java. </APPLET> <HR> The Example <A HREF="Acex.java">source</A>. <BR> The <A HREF="Account.java">Account</A> base class. </P> </BODY> </HTML> Figure 10.2 The Java Accounting applet processes transactions in vivid color.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Chapter 18 Development Tools for JScript and Live Content


q

Development Tools for JScript and Live Content r JavaScript Examples r Microsoft Technologies s ActiveX Control Pad s Microsoft FrontPage s Microsoft Visual J++ s Microsoft Visual SourceSafe s Microsoft Visual C++ s CafeBabe s ED s Jamba s Java JDKDevelopers Kit s Java IDE for Windows 95 s JavaPad r Shareware HTML Editors s 1-4-All s Almost Reality s DerekWare HTML Author s Dummy s FlexED for Windows 95 s HotDog Professional s HomeSite s HTML Edit s HTML Express s HTMLPad s INP s WebThing

Development Tools for JScript and Live Content


q q q

Some of the main topics in this chapter are Find JScript and VBScript source code you can use Learn about Microsoft's Internet tools Download the best shareware tools

In Chapter 11, "More About Java," you learned about some of the tools you can use to develop Java applets. And in Chapter 13, "More About ActiveX," you learned about the ActiveX SDK. This chapter expands on those tools by introducing you to the tools you need in order to develop great Web pages with HTML, ActiveX, JScript, and Java. Some of these tools are absolutely free; others are shareware programs that you can try free for a while. You pay for them only if you decide to keep and use them. Other tools described in this chapter are commercial products that you can get through commercial channels such as your corner computer superstore.

JavaScript Examples
The Internet is loaded with JavaScript (Microsoft calls it JScript) examples. In many cases, you can use those examples without worrying too much about copyright infringement. If in doubt at all, however, check with the original authors before you use their script in your Web page. If nothing else, you can rely on the scripts that you find on the Internet for inspiration when writing your own scripts. The following are some suggestions for finding scripts you can use:
q

Open http://www.yahoo.com/Computers_and_Internet/Programming_Languages/ JavaScript/Applets in your Web browser. This is a list of JavaScript applets. Most of them have scripts from which you can learn and, in some cases, scripts you can reuse in your own Web page. Open your favorite Web search tool. Use the keyword javascript with either demo, example, or sample. You'll see a list of JavaScript examples from all over the Internet. Microsoft's JScript site contains a number of JScript examples, including a mortgage calculator, Webzee (a Yahtzee knockoff), and Hangman. Open http://www.microsoft.com/ JScript/us/JSsamp/JSsamp.htm in your Web browser to try them out. I doubt Microsoft minds if you borrow some of their code. Gamelan is an awesome Web site that contains hundreds upon hundreds of examples. As of this writing, it contains 372 JavaScript examples. Open http://www.gamelan.com in your Web browser, and click the JavaScript link (in the middle of the Web page). You'll see several categories of JavaScript examples. In particular, click the Example link.

Microsoft Technologies
Most of the truly useful ActiveX and JScript development tools are from Microsoft. This section describes some of those tools, including the following: ActiveX Control Pad Microsoft FrontPage

Microsoft Visual J++ Microsoft Visual Source Safe Microsoft Visual C++

ActiveX Control Pad


The ActiveX Control Pad is a must-have utility if you're using ActiveX controls and JScript. It's an authoring tool that lets you automatically add ActiveX controls to your Web page--no hand-coding OBJECT tags, no hand-coding PARAM tags, just point and click, that's all. Take a look at Figure 18.1. Figure 18.1 The ActiveX Control Pad makes creating ActiveX Web pages much, much easier. The ActiveX Control Pad also helps you easily create JScript language scripts. In the Script Wizard, you associate an object's events with an object's properties and methods. Figure 18.2 shows you an example of associating a button's Click event with the Window object's alert method. Figure 18.2 You choose the properties and methods from the right pane that you want to associate with the events in the left pane. You'll learn everything you want to know about the ActiveX Control Pad in Chapter 19, "The ActiveX Control Pad." You'll learn how to download a free copy. You'll also learn how to use it to insert controls into your Web pages, create scripts using the Script Wizard, and use the HTML Layout control to create two-dimensional regions in your Web page.

Microsoft FrontPage
Microsoft FrontPage is the ultimate HTML editor. The best part is that you don't have to know one lick of HTML in order to use it for creating great Web sites. It's much more than just a pretty HTML editor, though; it's a tool you can use to manage your entire Web site. FrontPage contains the following two components:
q

FrontPage Explorer lets you create Web sites from scratch and even gives you wizards and templates to take you from no site at all to a site with a solid basis in only a few minutes. FrontPage Explorer gives you a structural view of your site, too. FrontPage Editor allows you to create individual pages or edit those pages you've created earlier in a what-you-see-is-what-you-get (WYSIWYG) editing environment. Figure 18.3 shows you what the FrontPage Editor looks like.

You can purchase Microsoft FrontPage at any computer retailer. You can get more information about FrontPage at Microsoft's Web site: http://www.microsoft.com/frontpage.

Figure 18.3 With FrontPage's server extensions, you can automatically stage and post your HTML files onto your Web server.

NOTE: A good alternative to Microsoft FrontPage is Adobe PageMill. It's a similar product that makes creating Web pages easy for those who are not programmers. For example, it works just like a word processor, so you'll be immediately familiar with many of its features. You create links by dragging an icon representing an URL and dropping it on an anchor. You even use a WYSIWYG editor to create tables. You can find more information about Adobe PageMill at http://www.adobe.com/prodindex/ pagemill/main.html.

Microsoft Visual J++


Microsoft has thrown its hat into the Java ring with Visual J++. This is Microsoft's first-rate development environment for Java Developers. Visual J++ is a comprehensive development tool you can use to build software components for the Internet. Following are some of the highlights of Microsoft J++:
q q

q q

Compiles over 10,000 lines of code per second. Includes an incredible debugger that you can use to disassemble bytecode, set breakpoints in your code, step through your code, watch variables, and more. Work with classes, methods, and variables using a class viewer (ClassView). Build event-driven Java applets using Visual J++ Wizards, which automatically generate basic code for you. Use the Visual J++ resource editor to create menus, forms, toolbars, and images.

You can purchase Visual J++ at most computer stores. You can also learn more about Microsoft Visual J++ at their Web site. Open http://www.microsoft.com/visualj in your Web browser.

Microsoft Visual SourceSafe


If you've built a Web site of any magnitude, you probably have dozens or hundreds of HTML files. Not to mention hundreds of graphics files. What's worse, you probably have more than one person working on those files, too. You need something to help you manage all those files. Keep all the different versions straight and manage conflicts between the different developers, artists, and the like. Take a look at Figure 18.4. Figure 18.4 Visual SourceSafe's user interface looks very similar to Windows Explorer.

Visual SourceSafe is precisely the right tool. It's a project-oriented version control system that manages your source files and the activities of the developers who work on them. When you want to work on a file, you check it out. This locks the file so that no one else can change it. Then, when you're finished with the file, you check it back in--unlocking the file. Visual SourceSafe keeps track of all the different versions so that you can keep a history of what's changed in the file. You can even roll back to a different version of the file if you make a mistake.

NOTE: Visual SourceSafe makes sharing files between multiple Web sites easy. You have one copy of a file that you share between multiple sites. Then, when you make a change to the file, that change is automatically reflected in all of the sites that share the file.

You can get more information about Visual SourceSafe from Microsoft's Web site. Open http://www. microsoft.com/ssafe in your Web browser.

Microsoft Visual C++


Currently, the only tool you can use to develop ActiveX controls is Microsoft's Visual C++, shown in Figure 18.5. You also need the ActiveX SDK, which you learned about in Chapter 13, "More About ActiveX." Figure 18.5 Microsoft Visual C++ contains a great editor, debugger, classes browser, resource editor, and more. There are two ways to build ActiveX controls using Visual C++:
q

You can build ActiveX controls using the Microsoft Foundation Classes (MFC). This isn't a good idea, however, because the MFC code is just too big to download over slow phone lines. You can build ActiveX controls using the ActiveX Template Library. This requires a reasonably complete understanding of the Component Object Model (COM), however. These controls download much faster, though, because they don't carry the baggage of MFC.

You've learned about some of the shareware HTML editors on the Internet. This section describes some of the shareware Java tools you can download and try out.

CafeBabe
URL: http://members.aol.com/opensolinc/opensolution.html CafeBabe is a freeware Java tool that you can use to view the revision, super class name, and methods in a class file.

ED
URL: http://www.getsoft.com This is an evaluation copy of ED, which is an integrated development environment for Java.

Jamba
URL: http://www.aimtech.com/prodjahome.html This is an evaluation copy of Jamba, which is a Java tool you can use to create Java applets without knowing much about Java programming.

Java JDKDevelopers Kit


URL: http://java.sun.com/JDK-1.0/index.html The Java Developer's Kit, from Sun Microsystems, is the standard for Java. It's freeware, too. You can use it with most of the shareware Java environments you see in this chapter or find it on the Internet.

Java IDE for Windows 95


URL: http://www.opennet.com/NetXS/index11.html Java IDE for Windows 95 is a freeware integrated development environment for creating Java applets.

JavaPad
URL: http://www.csn.net/express JavaPad is an editor you can use with Sun's Java Development Kit (http://java.sun.com/JDK). You can edit, compile, debug, and run Java applets within JavaPad. Tracking down errors is easy with JavaPad, too.

Shareware HTML Editors


The Web is just crawling with shareware HTML editors. Some of them are high-class, commercialquality products. Others are kind of junky, but they have features that make them worthwhile anyway. This section describes some of the most popular HTML editors.

NOTE: I've listed only the most notable HTML editors in this section. You'll find a comprehensive list of editors at Tucows, however. Open http://www.tucows.com in your Web browser for more information.

1-4-All
URL: http://ourworld.compuserve.com/homepages/minibbjd 1-4-All is a shareware HTML editor that comes with a wizard for creating frames and a table editor. It also has some predefined JavaScripts.

Almost Reality
URL: http://www.lm.com/~pdixon/index.html Almost Reality is a freeware HTML editor for Windows 95.

DerekWare HTML Author


URL: http://shell.masterpiece.com:80/derek DerekWare is a freeware HTML editor that supports all of the Internet Explorer HTML extensions. It has wizards for images, marquees, links, and forms. You can also add your own tags.

Dummy
URL: http://www.sausage.com/dumy.htm Dummy is a shareware utility published by Sausage Software (see HotDog Professional) that works more like a wizard. It provides step-by-step help for creating your home page from a predetermined style.

FlexED for Windows 95


URL: http://www.infoflex.com.au/flexed.htm FlexED for Windows 95 is a highly rated shareware HTML editor. You can edit the HTML directly, using dialog boxes to set the attributes for each tag. It also provides a lot of wizards to format your

Web page for you automatically, based upon how you answer the questions. You can use this HTML editor even if you don't know one lick of HTML.

HotDog Professional
URL: http://www.sausage.com HotDog Professional is one of the single best shareware HTML editors available on the Internet. It has an easy-to-use user interface, and provides wizards to simplify your job. It also has features that Microsoft hasn't yet started to dream about, such as a built-in animation editor. It contains JavaScript language scripts that you can use to add special effects to your Web page.

HomeSite
URL: http://www.dexnet.com/homesite.htm HomeSite is a basic shareware HTML editor that does HTML 3.0. It has some nice features in it, such as multifile search and replace and a Windows Explorer-like view of your HTML files.

HTML Edit
URL: http://www.iac.net/~afi/htmledit/htmledit.html HTML Edit is an easy-to-use freeware HTML editor. It's a good choice for beginners.

HTML Express
URL: http://www.pe.net/~coolkev/htmlexpress.html HTML Express is a shareware wizard-type program that creates HTML pages in a snap. If you don't want to mess with a bunch of HTML tags, you should give this one a try.

HTMLPad
URL: http://www.intermania.com/~imania HTMLPad is a simple shareware HTML editor. It looks a lot like Notepad, but is geared toward editing HTML files.

INP
URL: http://inp.harbinger.net/products/index.htm

INP is a great tool to create a corporate Web page quickly. You answer a questionnaire, which is industry-specific, and INP generates an eight-page Web site as a result. It comes with a bunch of predefined graphics you can use on your Web site, including backgrounds and icons.

WebThing
URL: http://www.arachnoid.com/lutusp/webthing.htm WebThing is a highly regarded HTML utility. It covers text and tables, and outlines into HTML instantly.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Notice: This online version of the book has not been through the final proof reading stage that the book goes through before being published in printed form. Some errors may exist here that are corrected before the book is published. This material is provided "as is" without any warranty of any kind. Copyright 1997, Que Corporation. All rights reserved. No part of this book may be used or reproduced in any form or by any means, or stored in a database or retrieval system without prior written permission of the publisher except in the case of brief quotations embodied in critical articles and reviews. Making copies of any part of this book for any purpose other than your own personal use is a violation of United States copyright laws. For information, address Que Corporation, 201 West 103rd Street, Indianapolis, IN 46290 or at support@mcp.com.

Chapter 6 Interactive HTML Objects


q

Interactive HTML Objects r Customizing User Interaction Using JScript r Review of HTML Forms s <FORM>...</FORM> s <INPUT> s <SELECT>...</SELECT> s <OPTION> s <TEXTAREA>...</TEXTAREA> r HTML form Objects in JScript s Buttons, Check Boxes, and Option Buttons s Manipulating Text Fields s Validating and Submitting a Form

Interactive HTML Objects


If you have been reading this book through to this point, you have proven that you have more than just a casual interest in JScript (unless, of course, you've happened to open the book to this page while you are in the book- store!). This chapter continues with the "object" theme of this part of the book and introduces you to interactive HTML objects. They are interactive in that they allow you to respond in some way to input from someone who visits your site. When you finish this chapter, you should be well on your way to building your first set of JScript scripts for your site. Most of the sites that you find today were built using many of the concepts in this chapter. Once you have the ability to use forms to lay out input and output areas; to create buttons to accept questions, replies, or other input; and to use "back-end" JScript to interpret that input, you have the beginnings of a full-fledged application. The ability to use the Web browser's GUI (Graphical User Interface) to create small programs very quickly is quite compelling. What you should take from this chapter is the knowledge of building forms, as well as having a new view of forms. Before JScript, the form was basically just for typing in responses to questions, or making a selection among some choices. Now, the form can be a template that instantly responds to some action by your Web site visitor.

Customizing User Interaction Using JScript

JScript is one of the first scripting languages that applies an object-oriented approach (via its roots in Java) to writing and modifying Web pages. JScript takes expressions in HTML, such as: <A HREF="http://www.yahoo.com">Yahoo!</A> and creates an object with methods and properties similar to the ones you read about in Chapter 5, "Built-In JScript Objects." This chapter and the next take you through the objects in JScript that are created and used when you write HTML code--specifically those related to working with HTML forms. Forms provide a key way for you to build a user interface with which you can create miniature "applettes." An example of this is using HTML forms, buttons, and text boxes to allow a user to click buttons on a calculator and see the results immediately (see Figure 6.1). We will use the term applettes as an alternative to Java's applet--which is a small program that runs on your browser. JScript scripts are smaller, yet might perform many of the same tasks you see in Java. Thus, you could think of them as mini-applets. Figure 6.1 A Web site using a calculator in JScript. Before JScript, the process of creating and validating information that a user entered via a form depended heavily on sending and receiving information from a server-side CGI script. A CGI was often used for creating the actual form (generating HTML), validating the information--such as checking that all of the fields were filled in correctly--and sending a response back to the user confirming that the information had been sent successfully. All of these CGI operations were conducted on the server, so that all the information in the form had to be sent back to the server and manipulated. Using JScript, you can place much of the work on the client side, which can reduce dramatically the connection times between the client (the browser) and the server (your Web server). In terms of validating form information, you do this by allowing the script to inspect the contents of each field that the user has entered, and to present an alert to the user if the information does not meet some specific requirements--such as number of characters or whether the field is empty.

Review of HTML Forms


Before we delve into the secrets of JScript and forms, let's review the various HTML tags that allow you to create a form. Although you may already be familiar with these tags, it is good to review them in case you discover features you may not be taking advantage of currently. Table 6.1 summarizes these tags. Table 6.1 Quick Review of HTML Form Tags Tag <FORM ACTION="URL" METHOD="GET"></FORM> Meaning Defines a form

<FORM ENCTYPE="multipart/form-data"></FORM> Uploads a file via a form <INPUT TYPE="TEXT"> <INPUT NAME="somename"> <INPUT VALUE="somevalue"> <INPUT CHECKED> <INPUT SIZE=6> <INPUT MAXLENGTH="100"> <SELECT></SELECT> <SELECT NAME="somename"> <SELECT SIZE="6"> <SELECT MULTIPLE> <OPTION>sometext <OPTION SELECTED> <TEXTAREA ROWS="5" COLS="5">...</TEXTAREA> <TEXTAREA NAME="somename">...</TEXTAREA> <TEXTAREA WRAP=OFF> Input field Field name Field value Checked Field size (in characters) Maximum length of field Selection list Selection list name Number of options in list Multiple selections (more than one) Option Default Option Textarea Input Box size Textarea name Wraps the text

<FORM>...</FORM>
This tag must begin and end your form. The following are attributes of the <FORM> tag:
q q

ACTION is the location where you want this form to go. METHOD is the way in which you send this information. The METHOD is usually POST, but sometimes you can use GET. ENCTYPE is the MIME type of the information you upload to a server.

<INPUT>
This tag creates various input fields. For example, the following HTML code: <INPUT NAME="Address"> allows you to establish an input field for addresses within the form.

Pairing this tag with the following attributes allows you to manipulate specific field designations:
q q q

q q

NAME is the name of this field. VALUE is the string or numeric value that is sent with this field. CHECKED applies to check boxes and option buttons, and defines whether they are checked on page load. TYPE determines which type of input this field represents. The types are as follows (you can also see some of these types in Figure 6.2 and the corresponding HTML code in Figure 6.3): * TEXT--A plain text box. * PASSWORD--A text box that echoes bullets when you type into it. The bullets hide the typed text. * CHECKBOX--Renders a small box that indicates whether it is selected. Usually for Yes or No questions. * RADIO--Renders a small circle that allows you to choose one among many options. They are commonly referred to as option buttons. * IMAGE--Returns the coordinates of the image selected here (with x=num, y=num as the parameters returned). This is very similar to imagemaps, but is useful if you want to just return the xy value that someone clicks. The following is an example: <INPUT NAME="thisimage" TYPE="IMAGE" SRC="foo.gif" ALIGN="TOP">

q q q q

(This use of IMAGE doesn't require you to have a resulting map file on your server, and could be sent directly to a script for interpretation.) * HIDDEN--Is not displayed by the browser. Useful for storing special information for the CGI. * SUBMIT--When this is clicked, it submits the form. * RESET--Clears all input fields and resets to the defaults. * SIZE--The size of the input field (in number of characters) for text or password types. MAXLENGTH sets the maximum number of characters to be allowed within a field of a text or password type.

<SELECT>...</SELECT>
This tag presents either a scrolling list of choices or a pop-up menu. <SELECT> is generated in different ways, based on your choice of options. You can generate a single window that "pops open" to reveal all of the options. You can then select one, or see a scrolling list of options with up and down arrows much like a regular window--which allows you to see many choices at once. Pull-down windows are best for times when you want someone to choose one option, and it saves screen space. It's best when the number of options are fewer than five or so. If you have more than five, you should set the SIZE attribute to show the first five (or fewer) and enable the user to scroll through the rest. Figure 6.2 HTML supports various forms of input fields.

Figure 6.3 HTML source code of the input fields in Figure 6.2. The following list gives the attributes you use with <SELECT>. Try out many variations on a test Web page to see how changing the attributes changes the way the list is shown:
q q

NAME is the name of the data (required). SIZE determines how many choices to show. If set to 1 or omitted, it renders a pop-up menu. If set to 2 or more, it is a scrolling list. MULTIPLE allows you to select multiple options and always renders a scrolling list.

TIP: An often underutilized way to use this form element is to place a caption just under an image with <SELECT SIZE=1> and the caption text inside--one line to an <OPTION>. The result is a nice "pop-open" caption that allows you to use that saved space in other ways. Note, though, that the bar will be as wide as your longest line in the <OPTION> list.

<OPTION>
This tag designates a selectable item, and is used within the <SELECT> and </SELECT> tags. The following list describes the attributes an <OPTION> might have:
q q

VALUE is the value returned when the form is submitted, if this option were selected. SELECTED means that when the page is loaded, this option is selected by default.

<TEXTAREA>...</TEXTAREA>
This tag provides an area for a user to enter multiple lines of text. This defaults to four rows in length, with each row 40 characters wide. The following list describes each attribute you might use in a <TEXTAREA> tag:
q q q q

q q

NAME defines the name for the information (required). ROWS is the number of rows in this field. COLS is the number of characters wide that this field is. WRAP determines how text flows inside a text area. You have three options for this attribute (you can see examples of WRAP in Figure 6.4 and the corresponding HTML code in Figure 6.5): * OFF--No text wrap. * VIRTUAL--Text flows to the right border, then wraps to next line. It will be submitted as one line, without newlines. So, although the text appears to wrap, it will be one line when sent

to the server (or script). * PHYSICAL--Text flows beyond the right border beyond the text area window. When it is submitted, the text will be wrapped based on any newlines.

Figure 6.4 Select fields may have several different sizes. Figure 6.5 HTML source code for Figure 6.4.

HTML form Objects in JScript


This section introduces you to JScript's HTML objects that relate to forms. With each of these objects, you will see further how to build a form that will be able to respond instantly to user output. You will learn about buttons, check boxes, and option buttons. These form elements consist of all the "clickable" elements. Mouse clicks on these elements can be used to trigger JScript functions or to submit a form to either your home server or another script running elsewhere (perhaps in another frame or window). You will get quite a bit of mileage out of these elements, and JScript has enhanced them with its ability to monitor their status (such as whether an option button is on or off).

Buttons, Check Boxes, and Option Buttons


Now that you've had a brief refresher of the different HTML tags that build a form, you are ready to begin using JScript to bring new life to your forms. We will examine how JScript builds special objects as it reads your HTML code, and we'll explore how to use these objects to create an interactive form. The form Object. Whenever you declare a <FORM>...</FORM> in your Web page, JScript takes the information contained within that form and builds a form object. To create a form object, use the syntax in Listing 6.1.

Listing 6.1 Form Attriubtes


<FORM NAME = "formname" TARGET = "windowname" ACTION = "serverURL" METHOD = GET | POST ENCTYPE = "encodingType" [ onSubmit = "handlerText" ] > </FORM> The new attributes you might notice are TARGET and onSubmit. TARGET specifies the window

that the responses go to. The event handler onSubmit is optional. The text listed in the handlerText is evaluated when you submit this form via the Submit button or use the submit method in another part of your script. Once you have created this object, you can address its properties and methods in the following way:
q q q q

formName.propertyName formName.methodName(parameters) forms[index].propertyName forms[index].methodName(parameters)

JScript places each form it finds in a page into an array called forms. You can access each form either by its index in this array (with the first form at 0, the next at 1, and so on) or by its name. For example: <form name="thisform"> <input type=text name="input1" value="hi there!"> </form> By doing this, you create an object called thisform which also exists as document.forms[0]. You can access individual fields in this form--where you can either read that field directly, or send a new value to that field--which might (depending on the type of input field) dynamically change on the screen. To access information about this form, use the following naming conventions:
q q q q q

formName.action--From the ACTION argument formName.elements--To get to the input fields and others formName.encoding--From the ENCTYPE argument formName.method--From the METHOD argument formName.target--From the TARGET argument

For an example, see Listing 6.2.

Listing 6.2 Example of Accessing a Form Element in JScript


<script language="jscript"> <form name="thisForm" action="foo.html" ENCTYPE="text/ascii" method="GET"> </form> <!-- hide this code document.forms[0].method = "POST" document.write(document.thisForm.method)

--> </script> The return of Listing 6.2 is the following: POST The button Object. The button object is a new type of INPUT tag that allows you to create general-purpose buttons in a form. You can use these buttons to activate any function, to open a new URL, or perform any other action that JScript can initiate. To define a button object, use the following syntax: <INPUT TYPE = "button" NAME =" nameInside" VALUE = "nameOnButton" [onClick = "handlerText"]> This is an extremely useful object, and you will probably find yourself using this often to create buttons to run scripts, open new windows, or even cause the browser to leave your Web site altogether! You must use this inside a set of <FORM>...</FORM> tags. You access a button's properties and methods in the following way:
q q q q

buttonName.propertyName buttonName.methodName(parameters) formName.elements[index].propertyName formName.elements[index].methodName(parameters)

For example, Listing 6.3 creates a page that looks like Figure 6.6. Upon clicking the button, you will see an alert that looks like Figure 6.7.

Listing 6.3 Using a Button Form Element in JScript<HTML>


<HEAD> <TITLE>Button Example</TITLE> <script language="JScript"> <!-- hide me from other browsers function hey() { document.alert("Hey there! You pushed the button!") } // end hiding from other browsers --> </script> </HEAD> <BODY> <form>

<h1>Click below for an alert!</h1> <input type="button" name="alertbutton" value="Click Me!" onClick="hey()"> </form> </BODY> </HTML> Figure 6.6 Web page with Alert button example. Figure 6.7 Here's the alert! You can access the properties of the button object in Listing 6.3 by using the following: document.forms[0].elements[0].name or: alertbutton.name If you wanted to retrieve the name of the button as a string object, you could use either of the following examples--which would return Click Me!: document.forms[0].elements[0].value or: alertbutton.value

NOTE: Once you have created a button object, you can change its value, but the text on the button does not change to reflect this. This is because the button was written to the screen when the page was loaded, and cannot be changed unless the page is reloaded. Reloading the page alone does not implement the change, because the button reverts to its default value in the HTML code when it is reloaded. The only way to change this value is to set the value equal to some variable that can persist across page reloading. For more information on how to do this, see Chapter 9, "Creating Your Own JScript Objects."

The checkbox Object. The checkbox object is created inside a form and appears as a small box with or without a mark (usually an x or tick) inside it. Think of a check box as an On/Off switch. A user can flip this switch on or off by clicking his or her mouse inside this box. Clicking here can also trigger an onClick event in your script. You create a check box via the syntax in Listing 6.4.

Listing 6.4 Checkbox Object


<INPUT TYPE = "checkbox" NAME = "checkboxName" VALUE = "checkboxValue" [CHECKED] [onClick = "handlerText"]> textToDisplay Accessing the properties of this object is very similar to accessing the properties of the button object. The properties are as follows:
q q

q q

CHECKED indicates true or false to specify whether the check box is checked. DEFAULTCHECKED indicates whether or not the check box was marked checked upon page load. NAME indicates the name of the check box. VALUE indicates the value that is returned by the form if the check box is checked. (This defaults to On.)

Listing 6.5 is an example of using the checkbox object in a script (see Figure 6.8).

Listing 6.5 Using the Checkbox Object


<html> <script language="jscript"> function mystatus(){ (document.theForm.theCheckbox.checked) ? alert("The box is checked") : alert("The box is not checked") } </script> <form name="theForm"> <input type="checkbox" name="theCheckbox" value="myValue" onClick="mystatus()"> </form> </html>

Figure 6.8 A Web page with a check box. When you click the check box so that it is checked, you will see something like what is shown in Figure 6.9. If you then "uncheck" it, you will see an Alert box like that shown in Figure 6.10. Figure 6.9 Once the check box is checked, you see this alert. Figure 6.10 Clicking the check box off will give you this alert. The radio Object. This object allows a user to make a choice of a single selection from many. Usually, this is a list of related items from which you want the user to pick only one choice. The radio object is very similar to the checkbox object, except that a series of radio objects with the same NAME attribute toggle all of the option buttons off except for the one that was picked. In other words, when you click one option button in a group of related buttons, all of them will be off except for the one you clicked. You create a radio object using the syntax in Listing 6.6.

Listing 6.6 radio Object Syntax


<INPUT TYPE="radio" NAME = "radioName" [CHECKED] [onClick = "handlerText"]> textToDisplay Accessing information from the radio object is slightly different from accessing it from the checkbox object. Because all of the option buttons of a given group have the same NAME attribute, you access individual option buttons by adding an index value to the NAME. The format for doing this is as follows:
q q q q

radioName[index1].propertyName radioName[index1].methodName formname.elements[index2].propertyName formname.elements[index2].methodName

You can click a specific option button in JScript by using the following: radioName[index1].click() Listing 6.7 is an example of using option buttons with JScript. The result is shown in Figure 6.11.

Listing 6.7 Option Button Example


<form name = "game"> <input type = "text" name="output" size=15> <input type = "radio" name="choice" value = "rock" onClick ="game.output.value='The Rock'">The rock <input type = "radio" name="choice" value= "scissors" onClick ="game.output.value='The Scissors'">The scissors <input type = "radio" name="choice" value = "paper" onClick = "game.output.value='The Paper'">The paper </form> Figure 6.11 A Web page example of using option buttons to constrain user input. This piece of code allows a user to pick one of the three choices--rock, paper, or scissors--which then shows up in the text field box. If the user wants to choose a fourth alternative, say bomb, then he or she just has to type it into the box. This is a quick way for you to offer both a series of preset choices, as well as allow a user to enter her own customized choice.

Manipulating Text Fields


This section gives you experience working with the text-based input fields in an HTML form, and shows how you can use JScript to enhance these input fields' usefulness to you as a script writer. The hidden Object. Often, when you create an interactive form, you want to keep some information hidden, yet still pass this information on to the server when the form is submitted. This is often information about the user--perhaps when he or she last accessed your page, or some preference that he or she had set in the previous form that generated this one. You can keep track of this information with hidden fields. This field is often used in place of Internet Explorer's "cookies" for compatability with browsers that do not support the cookie specification. Hidden fields contain text information and are not displayed on the screen with the rest of the form. Internet Explorer cookies are small strings of text; they are either stored in a single file named COOKIES.TXT or in separate files in a folder named COOKIES. They are often used to store information about you or your computer that is used by various sites to "remember" some bit of information about you between visits to that Web site. The server writes this code to your machine and will reread it when you visit again. Although this feature is very useful, there are still debates as to its security and validity of use. To create a hidden object, use the following syntax: <INPUT TYPE="hidden" NAME="hiddenName" [VALUE = "textValue"]>

You can access the properties of this object by using the following:
q q

hiddenName.propertyName formName.elements[index].propertyName

For example, the following returns "hi there!": <form> <input type=hidden name=hideme value="hi there!"> </form> document.write(hideme.value); Using hidden fields adds a sense of "state" to the Web. What this means is that usually a Web site has no real way of knowing whether visitors to that Web site had just been there moments ago, or whether they are visiting for the first time. Using the hidden field, you can place a hidden reminder to yourself (you as the Web site) on the page they receive--such as a timestamp--and retrieve that reminder whenever they submit that form to you for more information. This is very similar to the process one might go through to enter a parking lot, pick up a tag, then return that tag when you leave. Your server can read that hidden field into a CGI script and respond to the user of the page with something like "Welcome Back! Here's what's changed since you were here last!" Another use might be that of a hidden field in a Web-based game which stores the current score, location, and state of a player. This information is sent back to the game engine every time the player moves to a new location. The password Object. The password input field in a form is very useful for those times when you need to create a login screen and keep the password of that login hidden from view or from being printed by some malicious user who sees the login screen. Any time you want the information hidden from sight as a user types that information on the screen, use the password input field. To create this as an object in JScript, use the following syntax: <INPUT TYPE="password" NAME = "passwordName" SIZE=integer [VALUE = "textValue"]> Accessing the properties and methods of this object once it is created is identical to previous examples and is shown as follows:
q q q q

passwordName.propertyName passwordName.methodName(parameters) formname.elements[index].propertyname formname.elements[index].methodname(parameters)

The password object uses the focus, blur, and select event handlers as methods. JScript

imposes certain security restrictions on the use of the password object, however. It is not possible to check the validity of a password before a user actually sends it back to the server for a login. This restriction was introduced to prevent authors of malicious script code from capturing passwords. For this reason, you cannot get at the value field of a password object.

NOTE: Don't confuse the password object with the hidden object. The password object conceals what a user types into a text entry field, while a hidden object simply hides the whole field. Both input types in some way hide information.

The text Object. The text input field in an HTML document is your workhorse for inputting many types of information. Most other types of input in forms are derivations of this kind of input. The text input field is simply a small box of a set size that contains a cursor when you click it. It allows a user using the form to type in information such as a name, a date, or any other kind of information. If the text a user types is too long for the box, it scrolls to the left to accommodate the additional text. In JScript, this field serves a new and exciting purpose. Not only can a user using the form enter information into this field, but the script itself can enter information as well. In Chapter 5, "Built-In JScript Objects," you saw a script that used this field to display a constantly changing digital clock. You create a JScript text object using the syntax in Listing 6.8.

Listing 6.8 Text Object Syntax


<INPUT TYPE="text" NAME="textName" VALUE = "textValue" SIZE = integer [onBlur = "handlerText"] [onChange = "handlerText"] [onFocus = "handlerText"] [onSelect = "handlerText"]> A real-world example of this would be the following: <FORM> <INPUT TYPE="text" NAME="todaysdate" VALUE="" SIZE="5" onBlur=" getDate()" onChange="setDate()" onFocus="alert(`Set the date')" onSelect="alert(`Really change?')"> </FORM>

The text object properties reflect the information you provide in the tag when you create the object. Table 6.2 is a listing of those properties with an example of how you would access them. Table 6.2 Text Object Properties Property Example Description The value of the input tag at page load time The NAME argument

defaultValue myText.defaultValue name value myText.name

formName.elements[0].value The VALUE argument

You can act on this object in a number of ways, either indirectly by another function, or directly by using the event handlers contained in the object. Tables 6.3 and 6.4 list the methods and event handlers associated with the text object. Table 6.3 Text Object Methods Method Example focus blur myText.focus() myText.blur() Description Equivalent to clicking this field Equivalent to clicking another field after using this one

select myText.select() Equivalent to dragging the mouse across all the text in this field-selecting it Table 6.4 Text Object Event Handlers Event Handler Example onBlur onChange <input type=text onBlur="alert (`blur!')"> <input type=text onChange="alert (`changed')"> <input type=text onFocus="alert (`start typing!')"> <input type=text onSelect = "alert (`text selected!')"> Description Runs "alert()" when focus leaves this field Runs "alert()" if the text has changed when focus leaves this field Runs "alert()" when user clicks in (or otherwise gives focus to) this field Runs "alert()" once some text in this field is selected

onFocus

onSelect

The script in Listing 6.9 places information about a link in a text field below a series of links when a user passes the mouse over each link. This illustrates how you can use other event handlers to pass information to a text field (see Figure 6.12).

Listing 6.9 Event Handlers and Text Fields


<HTML> <HEAD> <TITLE>Text Field Example</TITLE> <script language = "jscript"> <!-- hide from other browsers var num =0 function showLink(num){ if (num==1) {document.forms[0].elements[0].value= "one"; } if (num==2) {document.forms[0].elements[0].value = "two"; } if (num==3) {document.forms[0].elements[0].value = "three"; } } // stop hiding --> </script> </HEAD> <BODY> <form> <input type=text size=60 > </form> <a href="#" onMouseOver="showLink(1)">one</a><br> <a href="#" onMouseOver="showLink(2)">two</a><br> <a href="#" onMouseOver="showLink(3)">three</a><br> </BODY> </HTML> Figure 6.12 Using onMouseOver, you can display different text in a text field. As you pass your mouse over each link--one, two, or three--you see that the text in the text field changes as well. You can easily modify this code to display helpful information about links on your own page beyond the URL that displays at the bottom left of the browser window (which is called the status area). The textarea Object. When you need a user to input more than just one line of text in a form, you use the textarea input type. For example, this is the case if you are providing an e-mail feedback form and want to allow space for the user to type in a lengthy note. To create a textarea object in JScript, use the syntax shown in Listing 6.10.

Listing 6.10 textarea Object Syntax


<TEXTAREA

NAME ="textareaName" ROWS = integer COLS = integer WRAP = on|off|physical|virtual [onBlur = "handlerText"] [onChange = "handerText"] [onFocus = "handlerText"] [onSelect = "handlerText"]> textToDisplay </TEXTAREA> A textarea object uses essentially the same attributes, methods, and properties as does the text object (see Tables 6.2, 6.3, and 6.4). You can provide default text to display in this field by adding text between the <TEXTAREA>...</TEXTAREA> tags. Long Example: Foobar the Bazbarian. The textarea input field is used in Andrew Wooldridge's game, Foobar the Bazbarian. In this game, the user can click buttons to go north, south, east, and west, and pick up various objects along the way to eventually win the game. The game itself is very simple in its concept and is long in implementation only because of the many pieces of text input that can be displayed in the textarea window. In a way, this completely turns around the concept of a text area from one in which you require a user to input long lines of text to displaying something like a miniature computer terminal. Listing 6.11 shows this program's code, and Figure 6.13 provides a sample display of how it might look on a Web page.

Listing 6.11 Foobar the Bazbarian


<HTML> <HEAD> <TITLE>FOOBAR! The Bazbarian</TITLE> </HEAD> <BODY > <script language="JavaScript"> <!-- The Engine //variable declarations var location="0" var locDesc= new StringArray(16) var zero=0 var bonus="10" locDesc[0]='You are standing at the edge of a small island. Palm trees sprout everywhere and obscure your view to the East and South. The beach is bordered on the North and West' locDesc[1]='The beach is to the West. You see the remains of your wrecked ship here. The forest is to the East and the beach goes North and South.'

locDesc[2]='The beach is West of you. At the edge of the forest stands a silver cage with a beautiful princess who beckons for you to unlock the cage.' locDesc[3]='The beach laps at you from the West and South. The palm trees to the North and East sway in the wind. You hear screaming to the North.' locDesc[4]='The ocean borders the North. On the beach you see empty Coke cans and various other washed-up trash. ` locDesc[5]='You are surrounded by palm trees. A monkey waves at you. You hear screaming to the South.' locDesc[6]='In a clearing, you see a golden cage with a gorgeous princess waving at you. She begs you to find the key and let her free.' locDesc[7]='The beach borders to the South. There are graves here with names of other warriors like yourself who failed...' locDesc[8]='The beach borders the North end of the island. The wind blows fiercer here.' locDesc[9]='You are in the midst of palms. Footprints dot the sand in all directions.' locDesc[10]='A woman screams to the West. Sharp rocks hurt your bare feet as you wander...' locDesc[11]='The beach borders the Southern end of the island. You hear a strange sound to the East, like a storm in the distance.' locDesc[12]='You see a chest full of gold, jewels and many other things. Your search reveals....' locDesc[13]='The beach stops you short to East. There are the remains of a campfire here.' locDesc[14]='Bones litter the beach to the East. They look human. You hear a sound like rushing wind to the South. Palms trees obscure your view.' locDesc[15]='A large green Dragon turns to look at you as you enter the clearing. Its growl is like a Mack Truck stuck in high gear.' // functions function StringArray (n) { this.length = n; for (var i = 1; i <= n; i++) { this[i] = `' } return this

} function initgame(){ var intro = "Welcome to Foobar the Bazbarian! \r\nClick on buttons to navigate\r\nClick RESET to start over\r" document.forms[0].dialogbox.value=intro+locDesc[0] document.forms[5].score.value=zero document.forms[5].itemhere.value="None" document.forms[5].your1.value="Empty" document.forms[5].your2.value="Empty" document.forms[5].your3.value="Empty" document.forms[5].your4.value="Empty" location=0 } function upscore(addscore){ oldscore=document.forms[5].score.value; num1=parseFloat(addscore); num2=parseFloat(oldscore); newscore=num1 + num2; document.forms[5].score.value=newscore } function changeLocation(index){ force=parseFloat(location) + parseFloat(index); location=force; if (location==0){ document.forms[0].dialogbox.value=locDesc[0]; document.forms[5].itemhere.value="None"; } if (location==1){ document.forms[0].dialogbox.value=locDesc[1]; document.forms[5].itemhere.value="None"; } if (location==2){ document.forms[0].dialogbox.value=locDesc[2]; document.forms[5].itemhere.value="None"; } if (location==3){ document.forms[0].dialogbox.value=locDesc[3]; document.forms[5].itemhere.value="None"; } if (location==10){ document.forms[0].dialogbox.value=locDesc[4]; document.forms[5].itemhere.value="None"; } if (location==11){ document.forms[0].dialogbox.value=locDesc[5]; document.forms[5].itemhere.value="None";

} if (location==12){ document.forms[0].dialogbox.value=locDesc[6]; document.forms[5].itemhere.value="None"; } if (location==13){ document.forms[0].dialogbox.value=locDesc[7]; document.forms[5].itemhere.value="None"; } if (location==20){ document.forms[0].dialogbox.value=locDesc[8]; document.forms[5].itemhere.value="None"; } if (location==21){ document.forms[0].dialogbox.value=locDesc[9]; document.forms[5].itemhere.value="None"; } if (location==22){ document.forms[0].dialogbox.value=locDesc[10]; document.forms[5].itemhere.value="None"; } if (location==23){ document.forms[0].dialogbox.value=locDesc[11]; document.forms[5].itemhere.value="None"; } if (location==30){ document.forms[0].dialogbox.value=locDesc[12]; document.forms[5].itemhere.value="Key"; } if (location==31){ document.forms[0].dialogbox.value=locDesc[13]; document.forms[5].itemhere.value="None"; } if (location==32){ document.forms[0].dialogbox.value=locDesc[14]; document.forms[5].itemhere.value="None"; } if (location==33){ document.forms[0].dialogbox.value=locDesc[15]; document.forms[5].itemhere.value="None"; pit(); } if (location != 0 && location != 1 && location != 2 && location !=

3 && location !=10 && location !=11 && location !=12 && location !=13 && location !=20 && location !=21 && location !=22 && location !=23 && location !=30 && location !=31 && location !=32 && location !=33 ) { alert ("You cant go there! The water blocks your way."); location=parseFloat(location) - parseFloat(index); } //alert(force + " and location" + location); } function takeItem(){ if (document.forms[5].itemhere.value != "None") { document.forms[5].your1.value=document.forms[5].itemhere.value; upscore(bonus); } else { alert("There's nothing here!") } } function useItem(itemtouse) { if (itemtouse == "Key" && location == 2) { document.forms[0].dialogbox.value="You Win! The Princess gives you a big Kiss, and Hillary reluctantly returns you to the land of Bat....\rYAY!" upscore(1000); } else { if (itemtouse == "Key" && location == 12) { document.forms[0].dialogbox.value="You picked the wrong Princess. The Witch cackles as she shoots a bolt of flame at your head. You Die!" document.forms[5].score.value=zero } else{ alert ("I cannot use that here"); }} } function pit() { document.forms[0].dialogbox.value= document.forms[0].dialogbox.value + "\rDid I forget to mention the Dragon?

Oops. This huge monster thunders up and takes a big bite out of your face. You die." document.forms[5].score.value=zero } // end Functions // end The Engine --></script> <h1 align=center>Foobar the Bazbarian!</h1> <table border align=left><tr><td colspan=2><form><!-- form 0 --> <textarea rows="10" cols="50" name="dialogbox" wrap="virtual"> </textarea></form><tr><td><h4 align="center">Movement</h4> <table border ><tr><td></td><td><form><!-- form 1 --> <input type="button" Value="North" Name="GoNorth" onClick="changeLocation (-1)"> </form></td><td></td><tr><td><form><!-- form 2 --> <input type="button" Value="West" Name="GoWest" onClick="changeLocation (-10)"> </form></td><td align=center><B>GO</B></td><td><form><!-- form 3 --> <input type="button" Value="East" Name="GoEast" onClick="changeLocation(10)"> </form></td><tr><td><tr><td></td><td><form><!-- form 4 --> <input type="button" Value="South" Name="GoSouth" onClick="changeLocation(1)"> </form></td><td></td></table> <td valign=top><form><!-- form 5 -->Your Score: <input type="text" name="score"><br> Items Here: <input type="text" name="itemhere"><br> Your Items:<br> <input type="text" name="your1"><input type="button" Value="USE" Name="use1" onClick="useItem(document.forms[5].your1.value)"><br> <input type="text" name="your2"><input type="button" Value="USE" Name="use2" onClick="useItem(document.forms[5].your2.value)"><br> <input type="text" name="your3"><input type="button" Value="USE" Name="use3" onClick="useItem(document.forms[5].your3.value)"><br> <input type="text" name="your4"><input type="button" Value="USE" Name="use4" onClick="useItem(document.forms[5].your4.value)"><br> <input type="button" Value="TAKE ITEM" name="takeme" onClick="takeItem()"> <input type="button" Value="QUIT" name="quitme" onClick="history.go (-1)"> <input type="button" Value="RESET" name="resetme" onClick="initgame ()"> </form></table><p><font size="-1">Created and copyright Andrew Wooldridge</font><p> <hr align="50%">

You are FOOBAR, the Bazbarian from the land of Bat. You and the Princess of Zfoeps have been kidnapped by the Wicked Witch Hillary. As a challenge, Hillary has imprisoned herself and the Princess in two cages. You must search this small island to free the Princess! Search around and find the key to unlock her cage. If you let out the wrong girl you die! If you free the Princess you win! Click RESET to Start. <br clear=left> Email me if you find a bug. <a href="mailto:andreww@c2.org">andreww@c2.org</a> </BODY> </HTML>

Validating and Submitting a Form


This section covers the final pieces of information you need to complete your exploration of JScript and forms. The last two form-based objects, submit and reset, are accompanied by an example of a simple mail-in form that checks the input before it is sent back to you. The submit Object. The Submit button was originally intended in HTML to be the final button a user would click to send a form back to the server. It would submit information, send feedback, or present a structured request for new information (you see this in search engines like Yahoo!). With JScript, you can now use this button to also send all of the information collected in a form to another window on your browser, or to the same window itself, which causes the contents of the window to change in some way. An example of this is changing the background color of the window based on the user's preference on a form. You create a submit object by using the following syntax: <INPUT TYPE="submit" NAME="submitName" VALUE="buttonText" [onClick = "handlerText"]> Figure 6.13 Web page view of Foobar the Bazbarian. You access this object's properties and methods by the following syntax:
q q q q

submitName.propertyName submitName.methodName(parameters) formName.elements[index].propertyName formName.elements[index].methodName(parameters)

When you click a Submit button, it always loads a new page--even if that page is the same page you

were already on. This is useful in that you can use a form to change attributes of the current page and see them change when you submit the form. The submit object uses the onClick event handler and can be clicked by using the submitName.click method. The reset Object. The Reset button allows a user to completely reset a form's input fields to their defaults. You create a reset object in JScript by using the following syntax: <INPUT TYPE="reset" NAME="resetName" VALUE="buttonText" [onClick ="handlerText"]> To access its methods and properties, you use the same familiar syntax, as follows:
q q q q

resetName.propertyName resetName.methodName(parameters) formName.elements[index].propertyName formName.elements[index].methodName(parameters)

The Reset button uses the same onClick event handler and click method as does the submit object. A Simple Form Validation Example. Listing 6.12 is a simple script that checks all of your input to see that you have placed the correct information inside each field. It then submits the form.

Listing 6.12 Form Input Validation Example


<html> <HEAD> <script language="JavaScript"> <!-- hide me function testone() { if (document.forms[0].elements[0].value==""){ alert("Please put a name in the first field!") } } function testtwo (){ if (document.forms[0].elements[2].value.length <5){ alert("Please input at least 5 characters") } } function testthree(){ if (document.forms[0].elements[4].value=="No"){ alert("Please change field three!")

} } // end hiding --> </SCRIPT> </HEAD> <BODY> <form> <h1>Below is a series of fields that you must set before you can send this form</h1> <input type=text name=one value=""> Input your name (any text) <input type=button name=check value=checkme onClick="testone()"><p> <input type =text name=two >Input at least 5 characters <input type = button name=checktwo value=checkme onClick="testtwo ()"><p> <input type = text name=three value="No">Change this to something else <input type=button name=three value=checkme onClick="testthree ()"><p> </form> </BODY> </html> From the example in Listing 6.12, you can see how an input of type button was used in place of an input of type submit. In a real-world script, you could either use a button input type with an onClick event handler, which would then run a check on that specific field, or you could keep the Submit button and use an onSubmit event handler to run checks on all of the input fields at once. The difference here is that when you use onClick and the button, you can be more specific as to which area you are checking; whereas, using the more general onSubmit, you can check all the fields at once without asking the visitor to check them.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Chapter 13 More About ActiveX


q

More About ActiveX r The 3.2 Component Object Model s A Simple View of How COM Works s What Is an Interface? s Advantages of Interfaces s Types of COM Objects s Foundation COM Components r Examining OLE and ActiveX Controls r ActiveX s Examining Component Categories s Management of Data and Properties s Persistent Linking and Embedding s Instantiation of a Control s Summary of Requirements for Internet-Aware Controls

More About ActiveX


q q

The Component Object Model Types of COM objects

ActiveX and the COM standard Microsoft has combined and enhanced its OLE and OCX technologies and renamed the consolidated standard ActiveX. ActiveX refines the OLE specification for OLE controls, which makes them smaller and more efficient. New OLE interfaces are also defined enhancing control over data and property management. Using the the new ActiveX Control class, generated controls are lightweight and Internet-aware.

NOTE: Microsoft has recently turned ActiveX over to a steering committee which will oversee the development of the ActiveX standards. You can get more information by opening http://www.activex.org in your Web browser.

The 3.2 Component Object Model

The Component Object Model (COM) is a Client/Server object based model designed to allow software components and applications to interact with each other in a uniform standard way. The COM standard is partly a specification and partly an implementation. The specification defines mechanisms for object creation and communication between objects. This part of the specification is paper-based and is not dependent on any particular language or operating system. Any language can be used as long as you adhere to the standard. The implementation part is the COM library, which provides a number of core services to support the binary specification of COM.

A Simple View of How COM Works


When a client COM object wants to use the services of a server COM object, it uses one of the core services in the COM library. The COM library is responsible for creating the server COM object and establishing the initial connection between the client and server. The connection is made when the server returns a pointer to the client. The pointer points to an Interface in the server object. From this point forward, the COM library plays no further part in the process. The two objects are free to communicate with each other directly. Objects communicate through Interfaces. Interfaces are small sets of related functions that provide some sort of service. An object may have more than one interface. When a client object has a pointer to a server object Interface, the client may invoke any function available through the Interface. When an object is finished using the services provided by another object, the client informs the server that it is finished and terminates communication. Please note that software objects may be client objects, server objects, or both.

What Is an Interface?
COM Interfaces are discrete sets of logically or semantically related functions. Interfaces are used to supply a service from a server object to a client object. Client objects never see the internal representation of the server object. An Interface can be thought of as a type of contract between two software components. The contract states that the server supplies the client with one type of service and nothing more. In a complex system, human readable name clashes are a fact of life. In order to avoid these clashes, Interfaces are given a unique name. It is called a Globally Unique Identifier (GUID). This is a 128-bit number that is almost guaranteed to be unique. (According to the official COM specification, 10 million GUIDs could be generated every second for the next 3,500 years or so and every single one would be unique!) GUIDs are also used in other parts of COM and OLE to assign unique names. Interfaces may also be given human readable names but these are locally scoped to a single machine.

Server objects that supply more than one service implement an Interface for each service they supply. A client may invoke functions in Interfaces only on the server objects for which they have a pointer. They may obtain pointers to other Interfaces through the IUnknown interface. This is a fundamental Interface that all COM objects must support. This Interface has a function called QueryInterface. Since all Interfaces are derived from IUnknown, this function is present in every Interface. This function knows about every Interface in the server object and can give a client a pointer to any of the Interfaces to which it requests access. A client may not know about every interface in the server. The server may have other Interfaces that a client does not know about. This in no way compromises a client's ability to use a server. It uses the interfaces that it knows. When a client is finished using a server, it informs the server that it is finished. This allows server objects to release themselves from memory when they are no longer servicing any clients.

Advantages of Interfaces
Interfaces allow objects to evolve independently over time. The definition and functionality of an Interface is never changed. If the functionality of an Interface changes or new functionality is added to the object, then a new Interface is added. This allows a server object to continue to be used by clients who know only about the old Interfaces. New clients who know about the new interfaces can use them as well as the old Interfaces. Interfaces allow objects to be replaced by better objects from a different vendor as long as the Interface definitions do not change. Interfaces are language independent. Any language that can create structures of pointers, and either explicitly or implicitly call a function through a pointer, can implement COM interfaces--languages such as C, C++, Smalltalk, and Pascal.

Types of COM Objects


There are three different types of COM server objects:
q

In-Process Servers--These server objects can be loaded into the client's process space. Under the Microsoft Windows operating systems, these objects are implemented in Dynamic Link Libraries (DLLs). Local Servers--These server objects run in a separate process on the same machine. This type of server is usually another application. Remote Servers--These server objects run on a remote machine connected by a network. These objects always run in a different process space. Remote servers may be implemented as either Dynamic Link Libraries or applications.

COM is designed such that regardless of where a server object is running, a client object always

communicates with it in the same way. There is one single programming model for all types of objects. A client object accesses the services of the server object through a pointer to an Interface on the object. If the server is running in process, then the pointer accesses the Interface directly. If the server is a local or a remote server, then the pointer accesses a proxy server running in the same process as the client. This proxy is supplied by COM. Its purpose is to generate a call to the appropriate server, either local or remote. At the other end, a stub object supplied by COM receives the call and turns it into a call on the Interface. Both client and server therefore always communicate with some piece of in-process code.

Foundation COM Components


Although COM is fundamentally concerned with object creation and communication, it provides the following other system level objects based on the fundamentals:
q

Persistent Storage Objects--COM defines a standard set of Interfaces that allow other objects to save their state to a persistent storage device. The implementation of these interfaces provides structured files. Information within such a file can be arranged in a hierarchical fashion, much like MS-DOS directories and files. It is often considered a file system within a file. Other benefits it offers are trans-actioning and incremental access. Applications may also browse the contents of a structured file to enumerate the named elements within it. Persistent Intelligent Names (Monikers)--COM defines a standard set of Interfaces for moniker usage. The implementation of monikers builds a lot of intelligence into a name. An instantiation of a particular object may be given a name such that a client can reconnect to the exact same instance of that object with the exact same state at a later time by merely specifying the name. Operations of some sorts may also be given a name that would allow clients to repeatedly perform the operation by using the name only. Uniform Data Transfer--COM defines standard interfaces through which a server and a client can exchange information. A client may also use these interfaces to register its desire to have the server inform it when the data it received changes. The COM standard also defines data structures, which can be used to describe the data and the medium through which the data passes between server and client (see Figure 13.1).

Figure 13.1 COM is built in progressively higher layers of technology. The object management services and the foundation COM components form the bedrock of information management. Microsoft's OLE 2.0 technology is built on this bedrock.

Examining OLE and ActiveX Controls


OCX controls are the standard solution for Windows component software. They are implemented

using OLE 2.0 technology and are designed for use on the desktop environment. Most OCX controls today are built using the Control Development Kit, which is supplied as an integrated part of Microsoft Visual C++ version 4.x. The controls built using this kit are excellent for use in the desktop environment. Some of these controls are even able to make the leap to the Internet environment without any modification. However, most will need to be modified to operate more efficiently and cooperatively. Controls developed with Visual C++ are built using the standard OLE 2.0 interfaces, some of which were mandatory. This means they contain a lot of unnecessary code. They are also dependent on the Microsoft Foundation Classes (MFC) libraries which are several megabytes in size. These controls are therefore relatively big in size which may limit their utility in the slow Internet environment. Also, in order to use these controls on the Internet, the user must first have the MFC libraries on their machine. A one-time download of these libraries for all controls to share may not be too much of a penalty, but MFC is being revised and released approximately every three months. This means users of these controls must download these new libraries every three months or their controls may not work. Management of data and properties is another potential problem. OCX controls on the desktop operate synchronously. Function calls made to the OLE libraries or a control container do not return until they have completed. While this is not a problem on the desktop, where data and properties are stored locally in files and can be retrieved quickly, it causes problems in a slow environment like the Internet, where large amounts of data have to be retrieved from a remote site and loaded into the control. A 24-bit bitmap file for instance, can be several megabytes in size and take many minutes to download. It would be unacceptable for the user's browser software to freeze during this process.

ActiveX
Microsoft has consolidated all its OLE and OCX technologies under the heading of ActiveX. ActiveX defines a new specification for OLE controls which allows them to be much smaller and more efficient. New OLE interfaces are also specified that address the problem of data and property management. Controls that are built using the new ActiveX lightweight control class are smaller than their Visual C++ control wizard generated counterparts, and they can use the new interfaces to function efficiently and cooperatively with control containers in the Internet environment. The OLE Control and Control Container Guidelines V2.0 defines a control as a COM software component that is self-registering, and implements the IUnknown interface. In order to support selfregistration, the control must export the DLLRegisterServer and DLLUnRegisterServer function calls. All the OLE interfaces that were previously mandatory are now optional. Controls are free to implement as many or as few of the standard interfaces as they require, which leads to the first question about ActiveX controls. Previously, a control container could depend on functionality being present in the control because of the mandatory OLE interfaces. If a control implements only the IUnknown interface, how does a control container, such as a browser or authoring tool, know or find out what a control's functionality is? The answer is Component categories.

Examining Component Categories

Component categories describe different prescribed areas of functionality. Each component category is identified by a Globally Unique Identifier and each defines a set of standards that a control must meet in order to be a part of that category. Component categories are stored as entries in the system registry with GUIDs and human-readable keys. Previously, when a control was registered on a client machine, it also registered the keyword Control under its CLSID. This keyword advertised the control's suitability for insertion into container applications such as Access and Visual Basic. The Control keyword is now obsolete, but it remains for the benefit of older applications that do not understand component categories. Component categories are a natural extension of this process. They allow a control to describe its functionality in far more detail than plain OLE interface signatures. When a control self-registers in the system registry, it adds entries under its CLSID for the GUID for a control, the GUID for each category that it supports, and the GUID of each category that it requires support for from a container in order to function properly. Additionally, it registers its own CLSID under each category registry entry (see Figure 13.2). Figure 13.2 Component categories are registered. Until now, when an application wanted to find out whether a particular control supported a piece of functionality, the application had to instantiate the control and use QueryInterface. If a valid pointer to a new interface was returned, then the application knew that the control supported the desired functionality. This is a very expensive and cumbersome operation. Using categories and new OLE interfaces in the OLE libraries that allow categories to be registered and unregistered, enumerated, and queried, means that an application does not have to instantiate a control anymore. It can get information about controls from the system registry through these new interfaces in one of two ways. If a control's CLSID is known to the application, then the application can retrieve the category GUIDs under the control's registry entry to find out the functionality of the control. If a specific area of functionality is required, then the application can go to the registry entry for the category and retrieve a list of the controls on the machine that have registered support for that functionality. It can then go to each control's registry entry and determine whether it can host the control. The list can then be presented to the user of the application via an application or system user interface, and the user can choose which control to use.

Management of Data and Properties


The major difference between controls designed for use on the desktop and controls that are Internetaware is the management of data and properties. A control may have any or all of the types of data listed in the following table which need to be stored so that they can be easily retrieved by a control container when it re-creates the control. These types do not imply any form of structure or storage location. A control's properties and BLOB data collectively make up its state.

Data Type

Size

Purpose The CLSID of the control class that can read the (CLSID data that follows Standard and custom property values

Class Identifier 16 bytes Properties Binary Large Around 10K-30K

Any number of large binary files. These files may Arbitrary size Objects (BLOB) be in any format. (for example, bitmaps, multimedia files, and so on

) If a control has no persistent state, then none of the above are present in an HTML document. The control container CLSID retrieves the CLSID of the control class directly from the attribute of the HTML <OBJECT> tag or indirectly from the CODE attribute. The control can then be instantiated and no further initialization is required. When the user of an application that is hosting a control gives the command to save, the control container calls QueryInterface on the control for a persistent storage interface and the control serializes its state through it. Similarly, when a control is re-created, it retrieves its state through a persistent storage interface. Where the application stores the control's state is up to the user of the application that is hosting the control. The control is not concerned. It may be embedded within the HTML document or in a separate file that is linked to the HTML document. This linking and embedding mechanism is familiar territory to anyone with knowledge of OLE compound documents. Although the control is not concerned with the actual storage of its state, it is concerned with the interfaces through which its state is saved and retrieved. One of the goals Microsoft had when creating the ActiveX specification was to introduce as little new technology as possible. However, the existing persistence interfaces used in the current OLE compound document architecture are potentially unsuitable for Internet-aware controls. In OLE compound documents, an object and its native data can be stored in two ways (see Figure 13.3). They can be embedded in the document or linked to the document. In the embedding case, the object's CLSID, its native data, and a presentation cache are stored within the document. In the linking case, a moniker and a presentation cache are stored within the document. The moniker points to a file that contains the object's CLSID and native data. Figure 13.3 Data can be stored in embedded and linked documents. The problems with this architecture are as follows:
q

The compound document usually always contains a presentation cache. This can lead to document sizes that are too large for effective use on the Internet. Embedded objects can use only the IPersistStorage interface for saving and loading data. This interface is a heavy-duty interface and is not well-suited to small, simple controls. Implementing this interface leads to code that is not required and is simply extra baggage for

small, simple controls.


q

When a compound document re-creates an object, the object retrieves its native data and properties synchronously. That is, when an object makes a call to a persistence interface to retrieve data, execution control does not return to the object until the data has been completely retrieved. This is not a problem on the desktop, as the data is stored locally in files on a highspeed disk subsystem. The length of time for which the user interface is frozen while retrieval takes place, therefore, is usually very small. In a relatively slow environment like the Internet, synchronous retrieval of large amounts of data from a remote site freezes the user interface for an unacceptably long time. If an OLE compound document wants to use linking to save an object's native data and properties, then it must implement the IPersistFile interface for moniker binding. File monikers, however, are designed to work with Universal Naming Convention (UNC) file and path names. They do not work with the Uniform Resource Locator (URL) file and path names that are used on the Internet. Any references to external data that are contained within the embedded or linked object's native data are known only to the object that created the data. This prohibits the control container from participating in the retrieval of the external data. Asynchronous retrieval of this data may not be possible.

Persistent Linking and Embedding


The problem of the presentation cache was eliminated for the embedding scenario in the first release of the OLE control specification in 1994. Controls could implement a new lightweight interface called IPersistStreamInit, which can be used in preference to IPersistStorage. IPersistStreamInit allows all properties and BLOBS to be channeled into one stream and stored by the application in the document. This eliminated the cache as the data could simply and quickly be reloaded into the control when the document was loaded and the control was instantiated and initialized. In the linking case, because the object's data and properties were stored locally in files and could be retrieved quickly, the presentation cache was also eliminated. Because of the shortcomings of the existing persistence mechanisms, Microsoft developed new persistence mechanisms and monikers that extend the concept of linking and embedding beyond the OLE Compound Document architecture (see Figure 13.4). These new mechanisms also allow for asynchronous retrieval of properties and BLOBs from remote sites, and are as follows: Figure 13.4 The new extensions employ the concept of persistent linking and embedding.
q

Persistent Embedding--The control's CLSID, properties, and BLOBs are stored within the HTML document itself. This is really useful only where the aggregate size of this information is small. It is not suitable for large amounts of data as the time taken to download the page and make it active would be unacceptable.

Persistent Linking--A single URL moniker is stored in the HTML document. This moniker points to a file on a remote site that contains the CLSID, properties, and BLOBs for the control. The specification of embedding and linking in OLE compound documents entails adherence to certain user interface standards. Specifically, linked objects may not be in-place activated. Persistent linking and embedding are not concerned with user interface and the standards are not relevant. Their sole function is for storage management of properties and BLOBs. Controls that are in-place activated, therefore, can still work with persistently linked data.

The persistent interface mechanisms that can now be used by a control are summarized in the following table: Use Mechanism Comments Standard persistence mechanism used in OLE compound documents. The container supplies an IStorage pointer to a storage object. The control may create any data structure within that object for its state. This is a lightweight alternative to IPersistStorage. All of the control's state can be serialized into one stream. The container defines a fixed size block of memory into which a control saves or retrieves its state. The control must not try to access memory outside the block.

Embedding/linking IPersistStorage

Embedding/linking IPersistStreamInit

Embedding/linking IPersistMemory

Embedding Linking

IPersistPropertyBag The container and control exchange property/ value pairs in Variant structures. IPersistFile The container gives the control a UNC filename and is told to save or retrieve its state from that file. The control is given a moniker. When the control reads or writes its state, it may choose any storage mechanism (IStorage, IStream, ILockBytes, and so on) it wants. If the storage mechanism chosen by the control is asynchronous, then IPersistMoniker must support asynchronous transfer.

Linking

IPersistMoniker

For each mechanism that a control implements, the control container must provide the appropriate support. A control container that wants to support embedding must provide the appropriate support for the

persistence interfaces exposed by the control, as in the following table: Control Persistence Interface Container Supplied Support IPersistStreamInit IPersistStorage IPersistMemory IPersistPropertyBag IStream IStorage Memory (*void) IPropertyBag

A control container that wants to implement linking must use a moniker that can supply support for the persistence interfaces exposed by the control. At the time of writing, the only available moniker is the URL moniker. If a control implements the IPersistMemory or the IPersistFile mechanism, it should also implement one other interface as both of these require that the data be present locally. These mechanisms do not work well with asynchronous downloads of properties and BLOBs. Controls are free to implement as many of these new persistence mechanisms as the developer of the control sees fit. For maximum flexibility, therefore, a control container should implement support for as many of these interfaces as possible. This ensures that it can work with a wide range of controls that may not implement all of the new persistence mechanisms. These new persistence mechanisms define the protocol through which the container and the control exchange information. What happens when an application decides to save a control's state (perhaps in response to a user request) depends on the application's (user's) preferences for storage. It can either be embedded in the HTML document or in a separate file and linked to the document. When embedding is used, the control container chooses which persistence interface to use. The sequence in which a container looks for persistence interfaces is generally up to the designer of the container. However, IPersistMemory and IPersistStreamInit may be given precedence over IPersistProperyBag and IPersistStorage, as they generally produce the smallest amount of data. It is perfectly acceptable for a container to have a control save its state in one location, and then copy it to another location. All that is required is that the container is able to retrieve the saved state and give it back to the control via the same interface. For example, a container could ask a control to save its state in a memory block. The container may then save the contents of that memory block in a storage location of its choosing. When the control is initialized, the container must retrieve the saved state and give it back to the control via a memory block. When linking is used, the container is not concerned with any of the persistence interfaces. The container must store and interact with an URL moniker. The moniker takes care of all the interface querying. URL monikers query for persistence interfaces in the following order:
q q q

IPersistMoniker IPersistStreamInit IPersistStorage

q q

IPersistMemory IPersistFile

In both linking and embedding, the container is responsible for the asynchronous transfer of data from the remote site. For more information on this, see the "Compound Files on the Internet" document supplied as part of the Sweeper SDK. All the persistence interfaces, with the exception of IPersistMoniker, are synchronous in operation. When a control receives a call to the Load member of one of its persistence interfaces, it expects all of the data to be available. Data paths serve two purposes. They allow a control to store its BLOBs separately from its properties, and they solve the problem of embedded links. Controls may have links to BLOBs buried in their native data that only they know. This prohibits the container from participating in the retrieval of these BLOBs. One solution to this is data path properties. Data path properties are properties that hold text string values. These string values are simply URL file names. Data path properties can be used with either persistent embedding (see Figure 13.5) or persistent linking (see Figure 13.6). Figure 13.5 Data paths in a persistently embedded document. Figure 13.6 Data paths in a persistently linked document. In a control's type library, data path properties must be marked as [bindable] and [requestedit]. This allows container applications to update these properties through their own user interface. These properties may also be updated through the control's property sheet. Properties are also tagged with a special custom attribute that identifies them as data path properties. The custom attribute is called GUID_PathProperty. It has its own GUID. Additionally, a control's coclass entry in its type library is also tagged with a special attribute that signifies that it has data path properties. This attribute is called GUID_HasPathProperties, and it, too, has its own GUID.

NOTE: Applications such as authoring tools and Web site management tools can query controls for data path properties and use them to perform link management or other tasks.

When a control wants to retrieve the file named by a data path property, it gives the URL to the container and asks it to create a moniker for the URL. The moniker is created in the implementation of the IBindHost interface. This interface is supplied as a service by the container site's IServiceObject implementation. In order for the control to call members of IBindHost, the control must provide a way for the container to pass a pointer that identifies the IServiceObject interface. A control could implement the IOleObject interface in order to achieve this. This interface has a function called SetClientSite that allows a container to pass the pointer to the

control. However, the IOleObject interface is a large interface. All its functionality may not be required by a small control. A smaller interface called IObjectWithSite can be implemented. It has just two member functions, one of which, SetSite, allows the container to pass the required pointer.

NOTE: Any control that uses data path properties must support a siting mechanism either IOleObject or IOleObjectWithSite. This is a requirement of the specification.

In order to get the IBindHost interface, two steps are required. First, the control calls QueryInterface on the site pointer for the IServiceProvider interface. Then, the control calls QueryService on the IServiceProvider interface for the IBindHost interface. In order to get a moniker for the file and data path property names, the control calls the ParseDisplayName function of the IBindHost interface. The data path may be either an absolute path name, or a path name relative to the location of the document. Either way, a moniker is returned, which the control can use to retrieve data. When downloading data, the control should be as cooperative as possible with the container and other controls by supporting asynchronous retrieval of data. This allows the user interface to remain active while data trickles down in the background. Before initiating a retrieval operation, a control should check to see whether the moniker that it is supplied with is an asynchronous one. It does this by calling QueryInterface on the moniker for the IMonikerAsynch interface. If this interface is not present, the moniker is synchronous and the control has to bind directly to the storage identified by the moniker by creating a bind context and calling the BindToStorage member of the moniker. If the moniker is asynchronous, the control should get its bind context from the container through the GetBindCtx member of IBindHost. By obtaining it this way, the container has a chance to register itself as an interested party in the download process. It can monitor the download and display some sort of progress indicator for the user's convenience, or perhaps allow the user to cancel the download. Once a control has the bind context, it registers its own FORMATETC enumerator and a pointer to its IBindStatusCallBack interface in the bind context. The control initiates an asynchronous download in the Load member of a persistence interface. In this function, another asynchronous stream should be obtained so that the moniker and the bind context can be released. This allows the Load function to return immediately, and execution control can return to the container. When data arrives, the OnDataAvailable member of the IBindStatusCallBack interface is called. The control should obtain the data exclusively through this function.

For detailed information on how the control, the container, and the moniker interact in asynchronous downloads, see the "Asynchronous Monikers" specification in the Sweeper SDK. Data transfer may be aborted by a call to the OnStopBinding member of the BindStatusCallBack interface. If a control receives such a call, there are two possibilities. The first possibility occurs if the control has received all its data. Then the call is merely a notification that the transfer is complete. The second possibility occurs when the data transfer has been aborted for some reason. A control may abort the data transfer by calling the Abort member of the IBinding interface. The control receives a pointer to this interface through the IStartBinding member of the IBindStatusCallBack interface. Because the container has control and data is trickling down in the background, you may wonder how a container knows when a control is ready to begin full interaction. One way to tell is to return a new code, E_PENDING, from member functions of the control when the control is not yet ready to fully interact. When this code is not returned, the control may be ready to interact. This, however, does not allow for progressive changes in a control's ability to interact with the application or the user. Microsoft solved this problem by defining a new standard property, ReadyState, and a new standard event, OnReadyStateChanged. When the control's ready state changes, the new standard event is fired with the value of the ReadyState property to notify the container. The ReadyState property may progressively have the following values: The control is waiting to be initialized through the Load member of a persistence interface. Loading The control is synchronously retrieving its properties. Some may not yet be available. Loaded/Can Render The control has retrieved its properties and is able to draw something through the Draw member of the IViewObject2 interface. Interactive The control may interact with the user in a limited way. It has not yet received all of its data from the asynchronous download. Complete The control is completely ready. The control does not have to support all of the above states. It has to support only as many as it needs. When a control is requested to save its state by a call to the Save member of a persistence interface, it saves all of its properties, including data path properties as strings, through the interface, and then saves all the BLOBs referred to by any data path properties. It does this by obtaining a moniker for each data path through the container's IBindHost as described above and synchronously saving the BLOB. When the Save function returns, a control is assumed to have saved all of its state. Uninitialized

Instantiation of a Control
The instantiation and initialization sequence for a control is as follows. The assumption is made that the control is already on the client machine and properly registered.

The application obtains the CLSID of the control from the CLSID attribute of the HTML OBJECT tag and instantiates the control. The DATA attribute contains either the property data encoded in MIME or an URL that names a file on a remote site that contains the property data. If the DATA attribute contains the property data, the container obtains a persistence interface on the control and calls the Load member with a stream containing the property data. If the DATA attribute contains an URL, the container makes an URL moniker and calls the IBindToObject member of the IMoniker interface in order to retrieve the property data from a remote site. Inside this function, the URL moniker attempts to get an IPersistMoniker interface on the control. If it succeeds, it passes a pointer to itself to the Load member of this interface. The control then has complete control over retrieval of its properties from the remote site.

NOTE: Because properties are usually very small amounts of data, measured in hundreds of bytes or so, asynchronous retrieval may not be the best method. Synchronous retrieval may be a better option as it may allow the control to become interactive sooner.

If it cannot get the IPersistMoniker interface, it gets another persistence interface. It then retrieves the property data, wraps it up in an IStream object if necessary, and calls the Load member function of the interface with a pointer to the object. The control then retrieves its property data from the IStream object. Inside the Load member of the persistence interface, the control also initiates any asynchronous download of BLOBS. It asks the container to make URL monikers so that the container may also bind to them and participate in the download process. The control binds to each moniker and registers its IOnBindStatusCallback interface in order to receive data. Control is then returned to the container. As BLOBs trickle down in the background, the control changes the value of the ReadyState variable and notifies the container of any change in its state through the OnReadyStateChange event. The ReadyState variable is passed as a parameter of the event.

Summary of Requirements for Internet-Aware Controls


If a control has no data path properties, then a control need implement only as many of the persistence interfaces as the developer sees fit. The more interfaces a control implements, the more flexibility it has for initialization by control containers and URL monikers.

Controls that have data path properties and BLOBs must meet the following requirements:
q q

They must support either IOleObject or IObjectWithSite as a siting mechanism. They must mark data path properties with the [bindable] and [requestedit] attributes as well as the custom GUID_PathProperty attribute. They must mark its coclass entry in its type information with the GUID_HasPathProperties custom attribute. They must follow the rules for moniker creation and persistence using the container's IBindHost as necessary. They must bind with an asynchronous moniker using a container provided bind context from IBindHost and receive its data through the OnDataAvailable member of the IBindStatusCallback interface. They must coordinate data retrieval and begin interaction as soon as possible.

Additionally, controls should supply a ReadyState variable and an OnReadyStateChange event if they are required. It should support IPersistPropertyBag for supporting HTML PARAM attributes.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Chapter 4 JScript Objects


q

JScript Objects r Objects, Properties, and Methods in JScript s Object-Oriented Programming Concepts s Defining Your Own Objects: The new Statement s Objects as Arrays s Using Variable Length Arrays and Extended Instances s The for...in Statement s Method Functions and this s Nested Objects s The with Statement s Functions with a Variable Number of Arguments r Built-In Objects s String Objects s The Math Object s The Date Object s The Array Object s Built-In Functions r Browser and HTML Objects s Browser Objects s HTML Objects

JScript Objects
q q q q

Use the Date, String, and Math objects Create New Objects with specific properties and Methods Build and use JScript arrays Understand the hierarchy of objects on a Web page

Associate HTML tags with HTML objects The idea of object-oriented programming is not a new one. It actually dates back over 30 years, and has gone through several phases of popularity in that time. Currently, object-oriented programming is considered by many to be an established concept that should be part of all modern programming languages. There are several different conflicting definitions of object-oriented programming. Fortunately, there are some key concepts that are shared by (almost) all versions of objected-oriented programming.

At its most basic level, object-oriented programming is a style of programming in which related concepts are grouped together. If you have five data elements and three functions that manipulate those elements, then you group those elements and functions together into a generic container known as an object. This is the common ground shared by (almost) all object- oriented programming languages. Differences arise in the details of how such containers are organized, and in how their contents can be accessed and modified. An analogy can be made between home ownership and object-oriented programming. Everyone's house has a kitchen, some bedrooms and bathrooms, stairs, flooring, and so forth. Some homes have spiral staircases, Art Deco ironwork, and a gazebo in the backyard. Others have a completely utilitarian layout based on a linear architecture with not a rounded corner in sight. When talking about your home, you describe both the basic aspects ("yes, of course, we have a basement") and also the embellishments ("the basement has a painfully hard cement floor"). When talking about what an object means in JScript, it's necessary also to talk of two levels. The basic aspects of the way JScript handles objects is known as its object model. The embellishments constitute the extensive set of features of the predefined objects in JScript, as well as those aspects of the language that can be used to create and use new, user-defined objects.

Objects, Properties, and Methods in JScript


Before we can delve into object-oriented programming in JScript, it is first necessary to review some of the basic concepts of object-oriented programming itself. You have already had a brief introduction in the "Functions and Objects" section of Chapter 2, "JScript: The Language." This section takes you further, and explains several critical and often misunderstood ideas.

Object-Oriented Programming Concepts


We already know that an object is basically a container for related items. Rather than carry around money and credit cards in many different pockets and folders, many people choose a more unified method: They keep their money in a wallet. Perhaps, they even keep their change in a change purse. The wallet is a container for related items. This is not to say that all such items must be in that wallet; this is often a near-impossible goal for even the most organized individuals. As a flexible principle, however, it is of enormous utility. Objects operate the same way. Objects collect related data items in a single place and make it simpler, or at least more logical, to access those items. As we have already seen, JScript refers to the items collected within an object as its properties. You may also recall that JScript objects not only store data, they also store functions. It is useful to keep functions that manipulate data items in a specific way with those data items themselves. These functions are known as the methods of an object. The JScript Date object is a perfect example of the benefits of this kind of organization. As the name implies, a JScript Date object is used to store a date, and also a time. The Date object also has a very particular set of methods that are useful in converting string representations of dates in Date

objects. While these functions are vitally important when manipulating strings such as "Nov 23, 1990," they do not really have sweeping application elsewhere. In a word, they are date-specific. It makes good sense to keep these methods with Date objects, rather than make them generally available functions. In addition to the concepts of object, property, and method, there is a fourth, somewhat more subtle, concept that is also of great importance: the instance. The relationship between an object and an instance of an object is the same as the relationship between a data type and a variable of that data type. In a typeless language such as JScript, this distinction is blurred but is still present. Another way to think of this distinction is to think of an object as a set of shelves, some of which may be occupied while others are not. You convert that object into an instance when you completely fill in all the empty shelves. While the object Date is an abstract thing that does not refer to any specific date, an instance of the Date object must refer to some specific date. Its empty slots, which specify the actual day, month, year, and so forth, have all been assigned specific values.

NOTE: Do not confuse the concept of a generic object with the much more specialized type of embedded object created with the HTML OBJECT tag. The latter is a considerably more advanced topic, which will not be discussed until Part III of this book, "Live Content and JScript."

Defining Your Own Objects: The new Statement


Now that we have presented the basic object foundation upon which JScript rests, it is time to consider how these concepts are implemented. How does one create objects and instances in JScript? In fact, you already know part of the answer to this question, as objects are created by defining a very special sort of function. Let's pursue the home ownership analogy even further and define a house object. The fundamental properties of our house object will be as follows:
q q q q

Number of rooms Architectural style Year built Has a garage?

To define an object to hold this information, we write the function shown in Listing 4.1. Note that this function makes use of the extremely important keyword this, which always refers to the current object. In this case, it refers to the current object we are creating.

Listing 4.1 Defining a Function to Create a house Object


function house( rms, stl, yr, garp ) { // define a house object this[0] = rms; // number of rooms (integer) this[1] = stl; // style, e.g. Colonial, Tudor, Ranch (string) this[2] = yr; // year built, integer this[3] = garp; // has a garage? (boolean) } There are several things to notice about this object definition. First of all, the name of the function is the name of the object: house. Second, this function does not return anything. When functions were first introduced in Chapter 2, "JScript: The Language," it might have seemed mysterious how a function could actually do useful work without a return statement, because everything inside a function is local. Using a function to create an object works by modifying this, so that it need not return anything. You can also have the function return(this). Using this explicit return statement has the same effect as the code shown in Listing 4.1. This example shows how a house object is defined. It does not create a specific house instance. The house object has four slots to hold the four properties: rooms, style, yearbuilt, and hasgarage. A specific house instance will fill those slots with actual values. Instances are created using the new statement combined with a function call. The keyword new is required, because it tells JScript that we are creating an instance rather than just calling a function. We could create an instance of house, named myhouse, as follows: var myhouse = new house( 10, "Colonial", 1989, true );

Objects as Arrays
Many programming languages support array data types. An array is an indexed collection of items all of which have the same underlying type. In C or Java, for example, we can say int iarr[10]; which defines a collection of 10 integers. These integers are referred to as iarr[0] through iarr [9]. These two languages use zero-based indexing, which means that the first element of the array is at location 0 and the last element of the array is at one less than the length of the array--9 in this case. Other languages such as Basic have one-based indexing, in which the elements range from 1 up to the length of the array. This might seem more intuitive, but zero-based indexing is actually the more common form. In the preceeding example, we created a new instance of the house object named myhouse.The instance myhouse is treated just like any other variable. It must be declared using var. Now that myhouse has been created, how do we refer to its properties? The [] notation in the house function looks suspiciously like an array reference. In fact, JScript also has arrays that use zero-based indexing. In JScript, however, arrays and objects are really two views of the same concept. Every object is an array of its property values, and every array is also an object. Our myhouse instance, for example, is an array with the following four elements:

myhouse[0] myhouse[1] myhouse[2] myhouse[3]

= = = =

10; // rooms "Colonial"; // style 1989; // yearbuilt true; // hasgarage

The various elements of the myhouse array contain its properties, which can be accessed by their numerical indices. myhouse[0] has the value 10, myhouse[1] is the string "Colonial," myhouse[2] is 1989, and myhouse[3] is the Boolean value true. The fact that the number of rooms and year it was built are integers, the style property is a string, and hasgarage property is a Boolean is only implicit, of course. There is nothing stopping us from creating a house instance in which the hasgarage property has the string value "yes" rather than a Boolean value. Care must be taken to avoid this kind of type confusion.

NOTE: Object properties are typeless, just like all other variables in JScript. The new operator does not protect you against inadvertently assigning an inappropriate value to a property.

In this form of object, it is possible to access the properties sequentially, which is often very useful. If we know that house objects always have four members, we can write the function shown in Listing 4.2 to display the property values.

Listing 4.2 A Function that Displays the Properties of a house


function showhouse( somehouse ) { // display properties of a house instance for( var iter = 0; iter < 4; iter++) { // four properties exactly document.write("<BR>Property " + iter + " is " + somehouse[iter]); } document.write("<BR>"); } If we call this function showhouse( myhouse ), the four properties of the myhouse instance are displayed. This function must be called with an instance, not an object. It would be an error to try showhouse( house ). Because there are several alternative ways of writing it, we will revisit this function when we have learned more about methods and the for...in statement. One deficiency of the showhouse function should strike you immediately. It relies on several pieces of implicit knowledge. We must remember that every house instance has exactly four properties, and we must remember which property is associated with each index. If we were to mistakenly use the myhouse[2] property as the hasgarage Boolean, rather than the yearbuilt integer, an error would no doubt result. In addition, if we augment the definition of a

house object by adding a property known as taxrate (a floating-point number describing the current real estate taxation rate on the house), then the showhouse function would need to be modified to increase the loop count in the for statement from 4 to 5. If we neglect to do so, the showhouse function would print only the first four properties, and would never print the taxrate. An even more disastrous error would occur if we redefined the house object to have only three properties, but forgot to drop the loop count to 3; then, the reference to somehouse[3] would refer to a nonexistent array member. This type of error is known as an out-of-bounds error, because it refers to an array element that was not within the boundaries of the array. Fortunately, JScript provides a simple means to address these issues. In JScript, it is possible to create arrays which are indexed by names, rather than numbers. We can rewrite the definition of the house object to reference its properties by name. This code for the new house object function is shown in Listing 4.3. This code can be found in the file house1.js on the CD-ROM.

Listing 4.3 house1.js--A Better house Object that Knows Its Own Properties
/* This function creates a house instance whose first property contains the number of properties in the house instance. All properties are referenced by name. */ function house ( rms, stl, yr, garp ) { this.length = 5; // four informative properties, and length this.rooms = rms; // rooms this.style = stl; // architecture style this.yearbuilt = yr; // year constructed this.hasgarge = garp; // does it have a garage? } This house object function takes four parameters, as before. It sets its length property to this number plus 1, because there are four meaningful properties (rooms, style, yearbuilt, and hasgarage) and the length property itself. More importantly, each of the properties is now referenced by name. If we create a myhouse instance, as before, we can now refer to myhouse. rooms, whose value is 10, myhouse.style, whose value is "Colonial", myhouse. yearbuilt, whose value is 1989, and myhouse.hasgarage, whose value is true. We can also use myhouse.length, whose value is 5, to tell us the total number of properties. This method of accessing instance members using the dot operator (.) is known, naturally enough, as dot notation. This use of the length property is a typical example of the true nature of object-oriented programming. One of the fundamental ideas in object-oriented programming is the idea of encapsulation, which is a long-winded way of saying keeping related things in the same place. In the previous definitions of house (see Listings 4.1 and 4.2), the length of the house object was present

in two places. It was implicitly present in the definition of house itself, and it was also present explicitly, as the upper limit in the for loop of the showhouse function. The doctrine of encapsulation says that this is bad. The length of an object should be stored only in one place--in the object itself. By the same token, it might be argued that the showhouse function should really be part of the house object, too. The "Method Functions" section later in this chapter describes how to do this.

TIP: Define all objects with a length property, which gives the number of properties in the object. Make the length property the first property.

It might seem that the two types of house objects, from Listings 4.1 and 4.3, are very different. In fact, JScript provides a powerful method by which objects created using the dot notation may be treated as arrays. Object properties may be referred to not only as indexed array elements but also as named array elements. This is why the JScript objects are also known as associative arrays. The set of properties of the myhouse instance created from Listing 4.3 could also be written as: myhouse["length"] = 5; myhouse["rooms"] = 10; myhouse["style"] = "Colonial"; myhouse["yearbuilt"] = 1989; myhouse["hasgarage"] = true; Following the preceeding advice, the first property of this object is its length, which we now know can be referred to as either myhouse.length or myhouse["length"]. We cannot refer to it as myhouse[0], however, even though it is the first property. Earlier versions of the JScript language, such as the original JavaScript that came with Netscape Navigator 2.0, did allow all three forms of access. The current implementation of JScript does not permit associative array elements to be accessed using numerical indices. This means that the showhouse function in Listing 4.2 will not work with the myhouse object created using Listing 4.3. The for...in statement, described as follows, will allow us to rewrite showhouse to work with the associative array form of house instances.

CAUTION: JScript arrays can be accessed either by integer indices or by property names, but not both. Property names are case-sensitive. Integer indices are limited by the length of the array. If you refer to nonexistent array elements, by name or by index, this either generates a JScript error or gives you an invalid value (usually null).

Using Variable Length Arrays and Extended Instances


There is one final point to be made about the difference between house object and its various instances. Suppose we create another instance of house, named yourhouse, using the following call to new: yourhouse = new house( 26, "Tudor", 1922, true ); myhouse and yourhouse are both instances of the house object. Both result from filling in the four slots in the house template with four specific pieces of information that define myhouse and yourhouse (as well as the fifth, hidden piece of information, the length). It is possible to dynamically extend an instance by simply tacking on a new property. If you feel the need also to record the fact that your house has two tool sheds and a gazebo, you can write: yourhouse.sheds = 2; yourhouse.hasgazebo = true; These two statements add two new properties to the end of the yourhouse array: the sheds (integer) property and the hasgazebo (Boolean) property. Dynamic extensions apply only to specific instances. The myhouse instance is not affected, nor is the house object changed in any way. If we execute showhouse( myhouse ), it prints out exactly the same as it did before. If we create a third house named pizza, as follows: pizza = new house( 3, "Restaurant", 1993, false ); it will not have a sheds property nor a hasgazebo property. Figure 4.1 illustrates the relationship between the house object and its various instances. Figure 4.1 Instances inherit their structure from the underlying object, but can also be extended.

NOTE: Dynamic extensions are completely local to a particular instance. The underlying object and all other instances--past, present, and future--are not affected.

There are some situations in which dynamic extensions are absolutely essential, and dramatically simplify programming. For the most part, however, dynamic extensions should be used with great care, as they can be the source of numerous errors. In fact, we have already made one such error, which shows itself if we attempt to execute the function showhouse( yourhouse ). Because the length element of the yourhouse instance has not been modified, it still has the value 5, so that only array elements 1 through 4 (properties "name" through "hasgarage") are displayed. The two new properties will not be displayed. When we added sheds and hasgazebo, we should have also said:

yourhouse.length += 2; to account for the two new properties in this instance. This is precisely the type of error that is easy to make. In general, it would be much better for the house object always to have sheds and hasgazebo properties, which are seldom used, than to randomly glue them on. The most efficient way to do this is discussed later in the "Functions with a Variable Number of Arguments" section of this chapter. The one common case where dynamic extension is extremely useful is in variable length arrays. Since object properties are just array elements, and since these elements can be referred to using a numerical index, it is easy to write an object creation function that creates an array of arbitrary size and content. The function in Listing 4.4 can be used to define an object that is an array of strings. The number of strings in the array is the first argument, and the initial value for each element is the second argument.

Listing 4.4 A Variable Length Array-of-Strings Object


function stringarr( howmany, initstr) { // "howmany" strings this.length = howmany; for( var i = 1; i <= howmany; i++ ) { this[i] = initstr; // initial value "initstr" } } If we call this function as: mystringarr = new stringarr( 100, "spoon" ); it creates an instance with 101 properties. The first named property, mystringarr.length, is the all-important length property. The next 100, at numerical indices 1 through 100, inclusive, are initialized to the string "spoon." Presumably at some point in the future, these 100 strings will be set to some other, less uniform values. It is important to initialize all the properties' values to something (the empty string "" would do in this case). Note that we could print the entire contents of this array by using a for statement such as: for(var oi = 1; oi <= mystringarr.length; oi++) document.write("Element " + oi + " is " + mystringarr[oi] + "<BR>"); If we later find that we need more than 100 strings, we do not need to create a new, even longer, stringarr instance. Instead, we can dynamically extend the array to include these new strings. It is essential that the length property be updated in this case, as there is no other way of determining how many elements are in the array, short of counting them with a for...in loop (see the following section). The following statements add three new strings and update the length: mystringarr[101] = "I'm"; mystringarr[102] = "doing"; mystringarr

[103] = "laundry"; mystringarr.length += 3;

The for...in Statement


Chapter 2, "JScript: The Language," introduced the extremely useful for statement. The standard form of the for statement begins with a clause that defines the initial state of the for loop, the condition under which it will terminate, and the way in which it is updated at the end of each iteration. There is also a variant of the for statement that may be used to iterate over the properties of an object. This statement, the for...in statement, has the following form: for ( varname in objname ) { forbody } In the for...in statement, varname is the name of a variable that takes on the successive property names of the object objname. This form of the for statement also permits the varname to contain a var declaration. Using the for...in statement, we can write yet another form of the showhouse function that will work with associative arrays, and that does not rely on the presence of a length property. This function is shown in Listing 4.5. This version actually works on any instance or object, not just on instances of house, so it has been renamed showany. This function can be found in the file showany.js on the CD-ROM.

Listing 4.5 showany.js--A Function that Displays the Properties of Any Object
function showany(anyobj) { // display properties of an instance or object for( var iter in anyobj ){ // iterate over all properties document.write("<BR>Property " + iter + " is " + anyobj[iter]); } document.write("<BR>"); }

Method Functions and this


One of the most powerful aspects of object-oriented programming in JScript is the ability to create objects with functional properties. You may recall that these functional properties are known as methods. Aside from being a convenient organizational principle, there are other distinct advantages to associating functions with objects. We have already seen the special keyword this that is used in object creation. It's also used in method functions to refer to the current object. To see how this works, consider one more variation on the house object and the showhouse function, shown in Listing 4.6 (the file HOUSE2.JS on the CD-ROM).

Listing 4.6 house2.js--The showhouse Function as a Method of house


/* This function creates a house instance with a "show" method */ function house( rms, stl, yr, garp ) { this.length = 5; // four info props and length itself this.rooms = rm; // rooms this.style = stl; // style this.yearbuilt = yr; // year built this.hasgarage = garp; // garage? this.show = mshowhouse; // the showhouse method } /* This function is the show method of the house object */ function mshowhouse() { // note: no arguments! var nprops = this.length; // len of property array not including show var idx = 0; for ( var iter in this) { //iterate if ( idx < 1 || idx >= nprops ) { idx++; continue; // skip "length" and "show" } document.write("<BR>Property " + idx + " is " + this[iter]); idx++; // increment numerical index} document.write("<BR>"); } This version of the instance creation function house not only has the usual four pieces of house information (rooms, style, yearbuilt, and hasgarage) and the length property, which gives the number of properties, it also has a final property named show, which is set equal to the function mshowhouse (it has been given a new name to emphasize that it is now a method function). Note that we deliberately did not count this method in the length of the property array: The value of the length property is 5, even though there are six properties. The method version of the showhouse function is shown next. It does not have any arguments. Instead, it refers to its enclosing object as this. The usual for loop works as before. We have deliberately shortened the length property by one and used an auxiliary variable named idx so that we can display the numerical index of each property. Only the first four properties of the house instance are displayed. We have used both a dot style (.) reference and an array style ([ ]) reference with this, which acts just like any normal instance. If we execute the show method on the

myhouse object, a display something like Figure 4.2 appears. Figure 4.2 Method functions can be used to display the properties of their instances. Because this function takes no arguments, you might wonder how it is used. The answer is that because the show method is a property just like any other property, it may be accessed in the same way. The statements: myhouse.show(); yourhouse.show(); pizza.show(); all work in the same way as their nonmethod counterparts: showhouse( myhouse ); showhouse( yourhouse ); showhouse( pizza ); This particular method function takes no arguments, and is also void; it does not return any value. Method functions can take as many arguments as you wish, and can also return values. Listing 4.7 shows a very simple method function that takes the current year and an argument, and returns the age of the house as its value. It checks the argument for validity and returns -1 if the current year is actually earlier than the yearbuilt property.

Listing 4.7 A Method Function for Displaying the Age of a House


function howold ( curyear ) { // current year passed as arg if ( curyear < this.yearbuilt ) // invalid year: too early return(-1); // no time travel (yet) return( curyear - this.yearbuilt ); // return difference } This method must be added to the object defining function house in order for it to work, of course. This function would be called by a standard property reference, such as: myhouseage = myhouse.howold( 1996 ); This type of function call is no different from a standard function call such as showhouse ( myhouse ). The only difference between method functions and other functions is that method functions may use this as an indirect way of naming the object that contains them.

TIP: If you have special purpose functions that operate only on instances of an object, then those functions should be methods of that object.

Nested Objects
Object properties are typeless quantities. They may be ordinary variables of any implicit type. Our house object contains properties that are implicitly integers, strings, and Booleans. It also contains functional members (methods). In a very real sense, every new object is a new data type, and every instance of that object is a new variable with its object as the underlying, implicit type of that instance. Since JScript is typeless, does this mean that objects can contain other objects? In a word, yes. Suppose we create a new object called desc, which holds some common pieces of information about various items. In particular, the desc, object has properties for length, width, height, and color, and a method for computing the volume. The definition of this object and its volume method are shown in Listing 4.8. This code can be found in the file descob.js on the CD-ROM.

Listing 4.8 descob.js--A Description Object and Its Volume Method


/* The object creation function. The len, width and height properties will be specified in meters. The color will be a string. */ function desc( ln, wd, ht, col) { // describe something this.length = 5; // four properties and length of the array this.len = ln; // length of the thing this.width = wd; // width of the thing this.height = ht; // height of the thing this.color = col; // color this.findvolume = findvolume; // volume computation method } /* The volume computation method. If the ismetric argument is true then the metric volume will be returned; otherwise the volume in cubic feet will be returned */ function findvolume ( ismetric ) { var mylen, mywid, myht; var conv = ( 39.37 / 12.0 ); // conversion from metric to English if ( ismetric == true ) { mylen = this.len; // metric by default mywid = this.width; // ditto

myht = this.height; // ditto } else { mylen = this.len / conv; // convert mywid = this.width / conv; myht = this.height / conv; } return( mylen * mywid * myht ); // return volume } We can now add a desc object as a property of the house object. We could simply add length, width, height, and color properties directly to the definition of house, but this would go against another fundamental principle of object-oriented programming: object reuse. The desc object is very general. It can be used to describe a house, a car, a boat, or a teacozy. It makes good sense to encapsulate these common properties in the desc object and then reuse that object's definition over and over by including it within the house, car, boat, and teacozy objects. It would be serviceable, but wasteful, to repeat the same information in all these object definitions. Listing 4.9 (part of the CD-ROM file house3.js) shows the latest version of the house object creation function.

Listing 4.9 house3.js--The house Object with a desc Subobject


/* This function creates a house instance with a "show" method and a "desc" subobject */ function house( rms, stl, yr, garp, desci ) { this.length = 5; // four info props and length itself this.rooms = rm; // rooms this.style = stl; // style this.yearbuilt = yr; // year built this.hasgarage = garp; // garage? this.descr = desci; // description instance this.show = mshowhouse; // the showhouse method this.howold = howold; // the howold method } In order to properly create a house instance, we must first create a desc instance and pass it as the fifth argument to house. It would be an error to pass in a desc object. A house instance, even one with a subobject, must have all its slots filled in; this is what makes it an instance. This means that all the slots in the desc property of house must be filled in, as well, so that it, too, must be an instance. Once this has been done, it is possible to use all the properties and methods of the desc of the house. Listing 4.10 shows code that creates a desc instance, creates a house instance with that description, and then displays the color, age, and volume of the house using the properties and methods of the desc (and myhouse itself). This type of structure, in which objects and instances can be contained within one another, is referred to as an object hierarchy. Listing 4.10 is also found in the CD-ROM file house3.js. When this code is executed, we obtain a page that looks like Figure

4.3.

Listing 4.10 house3.js--Creating and Using Subobjects


/* Create a desc instance and use it to create a house instance */ var mydesc; var myhouse; var mycol, myvol; mydesc = new desc( 20, 18, 15, "beige" ); // fairly big; ugly color myhouse = new house( 10, "Colonial", 1989, true, mydesc ); // mine, though /* Display the colorvolume and age of the house using a reference to the desc properties of myhouse. */ mycol = myhouse.descr.color; // property of property myvol = myhouse.descr.findvolume(true); // submethod document.write("<BR>My house is " + mycol); document.write("<BR>Its " + myhouse.howold( 1996 ) + " years old"); document.write("<BR>My house occupies " + myvol + " cubic meters"); document.write("<BR>"); Figure 4.3 Objects can contain one another in an object hierarchy.

The with Statement


Once you have become hooked on object-oriented programming, it often becomes a pervasive aspect of your coding style. Objects begin to show up everywhere. JScript has a convenient statement, borrowed from the Pascal language, that performs a set of object manipulations on the same object. Listing 4.10 may have impressed you with the power of its object manipulations. It may have also intimidated you a bit with the amount of typing that is required to get the color of the myhouse instance. The purpose of the with statement is to permit a number of object references to be made to the same object (or instance) without having to repeat the name of that object. The format of the statement is: with ( objname ) { statements

} objname is the name of an object or instance. Inside the with block, any reference to properties of objname occurs as if they had been prefixed with objname and the dot operator (.). Listing 4.11 shows an expanded version of the second part of Listing 4.10, in which various aspects of myhouse are displayed. The mshowhouse method should now be extended not only to display the properties of its instance, but also to call a similar show method within the desc object (which will also need to be created).

Listing 4.11 Using the with Statement as an Implicit Object Reference


/* Display the color and volume of the house using a reference to the desc properties of myhouse. */ var mycol, myvol, myage; with ( myhouse ) { mycol = descr.color; // 1: ref to myhouse.descr.color myvol = descr.findvolume(true); // 2: ref to myhouse.descr. findvolume myage = yearbuilt; // 3: reference to myhouse.yearbuilt document.write("<BR>My house is " + mycol); // 4 document.write("<BR>My house occupies " + myvol + " cubic meters"); // 5 // 6: explicit reference to another instance if ( myage > yourhouse.yearbuilt) { document.write("<BR>Its newer than yours!"); // 7 } document.write("<BR>"); } Each of the statements labeled 1, 2, and 3 makes an implicit reference to the myhouse object, which was established as the default object to use in the with statement. Note that not every statement within the with block need refer to myhouse. Statements 4, 5, and 7 make absolutely no reference to any house object. Also, statement 6 makes an explicit reference to a different house instance, namely yourhouse. Statement 6 exposes one of the weaknesses of the with statement. When JScript careens through this with block, it must decide many times when the implicit myhouse is to be used, and when it is to be skipped. It must examine every reference, in fact. So, for mycol, it must decide whether you meant the local variable mycol, or whether there is some property of myhouse named myhouse. mycol. Fortunately, there is an unambiguous choice in every case. There is no mycol property of the house object.

Statement 6 uses an explicit reference to yourhouse. If statement 6 had been written as: if ( myage > yearbuilt ) { JScript would have misinterpreted your intentions as to the meaning of yearbuilt, and would have implicitly translated this statement to: if ( myage > myhouse.yearbuilt ) { because there is a yearbuilt property of myhouse. This type of error is both common and pernicious. Because JScript is an interpreted language, there is no way to see that this inappropriate translation has taken place. There is no compiled output that can be examined. Such errors are very hard to debug. Even though with is very useful, its use should be strictly circumscribed.

CAUTION: with blocks should be as short as possible. Check all statements within the with block to ensure that there are no ambiguous references to local variables or to properties of other objects.

Functions with a Variable Number of Arguments


Our discussion of the object foundations of JScript is almost complete. We have learned that functions are used to define objects and create instances using the new operator. We have also learned that indexed arrays and associative arrays are both really objects. In fact, the unity between all these concepts goes even deeper. JScript functions themselves have properties that can be used to fine-tune their behavior. This aspect of JScript is still evolving at the time of this writing. However, we can say for certain that all JScript functions will have at least the following two properties:
q q

caller arguments

The caller property is a string containing the name of whoever called the function. The arguments property is an array of all the arguments that are not on the argument list of the function. The caller property permits a function to identify and respond to the environment in which it is called. The arguments property enables us to write functions that take a variable number of arguments. The arguments in the function's argument list are mandatory, while those in the arguments property are optional. Listing 4.12 shows a function that takes one mandatory argument and a potentially unlimited number of option arguments. It returns a string describing its invocation. This function is contained in the CD-ROM file optarg.js.

Listing 4.12 optarg.js--A Function with Mandatory and Optional Arguments


/* . Demonstrate mandatory and optional arguments to a function. Add all optional argument, and return the sum as a string. */ function addem( str1 ) { // one mandatory argument var nopt = addem.arguments.length; // # of arguments var sum = 0; // sum of optional arguments var strres; // string result for( var i = 1; i < nopt; i++ ) { // iterate over all optionals sum += addem.arguments[i]; // add them } strres = "Hello " + str1 + ", sum is " + sum; return(strres); } To see how this works, suppose that this function is called from within another function named test1, with the following invocation: var str = addem( "there", 1, 3, 5, 7 ); What happens? The mandatory argument "there" is assigned to the parameter str1 of the function addem. The complete argument list is also assigned to the variable length array addem. arguments. This has a length property (as do all well-behaved arrays), which has the value 5, because there are five arguments all together--one mandatory argument and four optional arguments. This means that the local variable nopt is 5. Unlike the examples we have used, the length property is not at index 0 of the arguments array. The arguments begin at addem.arguments [0] and continue up to addem.arguments[4] (five elements total). This means that the optional arguments begin at addem.arguments[1]. The for loop in addem adds the optional arguments together, and arrives at 1 + 3 + 5 + 7 = 16, which is assigned to the local variable sum. Finally, strres is constructed by concatenating various strings, among them the mandatory parameter str1, which is "there", and the value of the sum. The concatenated string is returned and assigned to str; its value is the string "Hello there, sum is 16." Notice that both the mandatory argument str1 and the optional arguments are part of the argument list addem.arguments. Notice also that there need not be any optional arguments. The function call: var str = addem( "on a stick" );

returns the value "Hello on a stick, sum is 0."

Built-In Objects
Now that we have covered the foundations of object-oriented programming in JScript, we can begin to look at the actual objects that JScript itself provides. These objects can be put into the following three categories:
q q q

Built-in objects HTML objects Browser objects

Built-in objects include the string objects, the Date object, the Math object, and the Array object. They are referred to as built-in because they really do not have anything to do with Web pages, HTML, URLs, the current browser environment, or anything visual. HTML objects, in turn, are directly associated with elements of Web pages. Every link and anchor is a JScript object. Every form, and every element within a form, is an HTML object. The hierarchical organization of display elements on a Web page is reflected almost exactly in a hierarchical set of nested HTML objects. You've already gotten a taste of this hierarchy in the event-processing examples of Chapter 3, "Events and JScript." See Chapter 3, "Events and JScript" for more information on the relationship between HTML elements and JScript functions. Browser objects are at the top of JScript's object hierarchy. These objects represent large-scale elements of the browser's current environment, and include objects such as window (the current window), history (the list of previously visited pages), and location (the URL of the current page). The rest of this section briefly describes the built-in objects of JScript. The next two sections give overviews of the HTML and browser objects. Each of these three categories is quite rich. Chapter 5, "Built-In JScript Objects," Chapter 6, "Interactive HTML Objects," and Chapter 7, "Advanced HTML Objects and Navigation," provide more in-depth information on each of the three categories.

String Objects
String objects are the most built-in of all the built-in JScript objects. You do not even need to use new when creating a string object. Any variable whose value is a string is actually a string object. Literal strings such as "HelloWorld" are also string objects. You can also use new on the string object to obtain a new string. The following statements both construct a string whose value is "hiya": var mystring = "hiya"; var mystring2 = new String("hiya");

String objects have one property--length--and many methods. The length property gives the length of the string. The methods fall into three categories: methods that manipulate the contents of the string, methods that manipulate the appearance of the string, and methods that convert the string into an HTML element. String Content Methods. The following methods can be used on string objects to access, control, or modify their content:
q q q q q q

charAt( idx ) indexOf( chr ) lastIndexOf( chr ) substring( fromidx, toidx ) toLowerCase() toUpperCase()

The toLowerCase and toUpperCase methods convert the contents of the string entirely to lower- and uppercase, respectively. So, if we define the string variable: var mystr = "Look At This" then its length property, mystr.length, will have the value 12, since there are 12 characters in the string. In addition, we can apply the two case conversion methods and get: mystr.toLowerCase() = "look at this" mystr.toUpperCase() = "LOOK AT THIS" These two functions do nothing to characters that have no case, so the two spaces in this string are unchanged. We could have also applied the methods directly to the literal form of this string object, so "Look At This".toLowerCase is also equal to "look at this". The methods charAt and substring are used either to extract a single character from a string, at position idx, or to extract a range of characters, from position fromidx up to but not including position toidx. Character positions are zero-based, as are all JScript arrays, so that all indices must fall between 0 and one less than the length of the array. For example, using mystr, we have: mystr.charAt(5) = "A" mystr.substring(5,7) = "At" Like the method functions toUpperCase() and toLowerCase(), these methods both return strings. Care should be take to give these methods valid indices that are actually within the string. The substring method will forgive you if you accidentally specify a toidx which is <= the corresponding fromidx--it will return the empty string "". Finally, both the indexOf and lastIndexOf methods are used to search for chr with a string.

indexOf searches from the beginning (left side) of the string and lastIndexOf searches from the end (right side). Both return an integer index if they find the character, and -1 if they do not. Using mystr again, we can search for the character o from both sides: mystr.indexOf("o") = 1 mystr.lastIndexOf("o") = 2 The first search finds the first o of the word "Look" at position 1 (second character), and the second search finds the second o of "Look" because that is the first o when searching from right to left. Both of these methods also take an optional second argument that specifies an initial index at which to start the search. String Appearance Methods The string appearance methods are used to control how a string appears when displayed on a Web page. If you are creating a page with standard HTML tags, you would achieve the same effects by using various tags. For example, to make the string "help" appear in italics, you would write <I>help</I>. The string appearance methods allow you to obtain the same effects in JScript without using the corresponding HTML elements. The string appearance methods are as follows:
q q q q q q q q q q q

big() blink() bold() fixed() fontcolor( colr ) fontsize( sz ) italics() small() strike() sub() sup()

Most of these methods should be self-explanatory. The italics method, for example, performs exactly the same function as the I tag in HTML. The only two that take arguments are the fontcolor and fontsize methods. The fontcolor method changes the font color of the string, as if the <FONT COLOR=colr> attribute had been used. Similarly, the fontsize method changes the size of the font used for displaying a string as if the <FONT SIZE=sz> attribute had been given. colr should be a string; sz may be a number or a string. If it's a number, this specifies an absolute font size; if it's a string such as "+2," it specifies an increment relative to the current font size. Listing 4.13 shows several examples using the string appearance methods. The output of this code is shown in Figure 4.4. These methods are described more fully in Chapter 5, "Built-In JScript Objects."

NOTE:

Not all HTML style tags have corresponding string appearance methods. You can always directly embed an HTML tag in the string itself if there is no method with the same functionality.

Listing 4.13 String Methods Can Be Used to Change How Strings Are Displayed
var bstr = "big"; var sstr = "small"; /* This displays strings with both big and small text. */ document.write("<BR>This is " + bstr.big() + " text"); document.write("<BR>This is " + sstr.small() + "text"); /* The following two strings contain directly embedded HTML tags. They have exactly the same result as the two method calls above */ document.write("<BR>This is <BIG>big</BIG> text"); document.write("<BR>This is <SMALL>small</SMALL> text"); /* If your favorite tag does not have a method, just embed it */ document.write("<BR>This is <STRONG>strong</STRONG> text"); document.write("<BR>"); Figure 4.4 Many HTML style tags have equivalent JScript methods. HTML String Methods. JScript provides two string methods for converting strings into hypertext entities. These methods should be clearly distinguished from the HTML objects, such as forms, which are discussed in the section on "Browser and HTML Objects" later in this chapter. These two methods are used to create HTML, while the HTML objects already are HTML. The two methods in this category are as follows:
q q

anchor( namestr ) link( hrefstr )

Both these methods are used to create some form of the anchor (<A>) HTML attribute. The difference between them is that the anchor method is used to create an anchor with namestr as the value of the NAME attribute, while link is used to create an anchor with the HREF attribute set to hrefstr. Said another way, anchor creates an anchor that is a target, while link creates an

anchor that is a link. Both methods convert the string on which they operate into the text portion of that anchor. namestr may be any valid string which may be a NAME, so it should not have any embedded white space. hrefstr should be a valid URL, because the user is being invited to click it. Listing 4.14 uses these methods and shows a simple example that sets up an anchor target and then links to it. NOTE: The anchor() string method uses the older but more common HTML NAME attribute rather than the newer ID tag.

Listing 4.14 String Methods Can Be Used to Create HTML Anchors and Links
var sum4str = "Summary of Chapter 4"; var sum4tar = "Summary4"; /* Create a summary target and a link to it. The following two statements are completely equivalent to this HTML: <A NAME="Summary4">Summary of Chapter 4</A><HR> Click here for a <A HREF="#Summary4">Summary of Chapter 4</A> */ document.write(sum4str.anchor(sum4tar)); document.write("<HR>"); document.write("Click here for a " + sum4str.link(location + "#" + sum4tar)); document.write("<BR>");

The Math Object


The Math object is used for various forms of mathematical calculations. It contains several properties that are standard constants, such as pi = 3.14159..., as well as a large set of methods that represent common trigonometric and algebraic functions. All Math methods deal with floating-point numbers. Angles are expected to be given in radians, not degrees. The Math object is our first example of a static object. A static object is one that does not change. All of the slots in the Math object already have values. This makes perfect sense, because you cannot change the value of pi or invent a new meaning for the cos() function (without creating chaos). The practical consequence of Math being static is that you never use new with Math; you always refer to the Math object directly. Static objects, such as the Math object, are different from "ordinary objects," which have themselves as well as their instances. The Math object has only itself, and no instances.

The Math object has the following properties:


q q q q q q

E LN10 LN2 PI SQRT1_2 SQRT2

The Math object has the following methods:


q q q q q q q q q q q q q q q q q

abs( num ) acos( num ) asin( num ) atan( num ) ceil( num ) cos( ang ) exp( num ) floor( num ) log( num ) max( num1, num2 ) max( num1, num2 ) pow( num1, num2 ) random() round( num ) sin( ang ) sqrt( num ) tan( ang)

These are all the functions and constants you find on any decent calculator. Remember that JScript is case-sensitive, so you must write Math.PI exactly to get the value of pi. The constants stand for the base of the natural logarithm (Napier's constant, or about 2.71828), the natural log of 10 (about 2.30259), the natural log of 2 (about 0.69315), everyone's favorite pi (about 3.141592653589793), the square root of 1/2 (about 0.7071), and the square root of 2 (about 1.4142).

NOTE: Internet Explorer 3.0 does not yet support the properties Math.LN2E and Math. LN10E provided by Netscape Navigator 3.0.

The methods of the Math object include the common trigonometric functions, including the sine (sin), cosine (cos), tangent (tan) and their inverses, the arcsin (asin), arccos (acos), and arctan (atan). Each of the trig functions takes an angle in radians and produces a floating-point number.

The values should be between -1 and 1 for the sin and cos methods. Each of the inverse trig functions takes a number, which should be between -1 and 1 for the asin and acos methods, and returns an angle in radians. The ceil, floor, and round methods all take floating-point numbers as inputs, and return integers as outputs. The ceil method gives the smallest integer that is greater than or equal to its argument, while floor returns the largest integer that is less than or equal to its argument. The round method gives the nearest integer. The exp, log, pow, and sqrt methods all deal with exponentiation or its inverse. The exp method raises Math.E to the power given by its argument, and is the inverse of the log method, which returns the natural logarithm of its argument, which should be positive. The pow method raises num1, its first argument, to the power num2, its second argument. The sqrt returns the square root of its argument. If you inadvertently give sqrt a negative number, it forgives you and returns 0. Finally, the abs, min, max, and random methods perform various useful operations. The abs method returns the absolute value of its argument. min and max give the minimum and maximum value of their two arguments, respectively. The random method takes no arguments. It returns a random, floating-point number between 0 and 1. Although older releases of IE did not support random(), all current versions do. Listing 4.15 presents some simple uses of the Math object. This example can be found in the CD-ROM file mathex.js. More detailed examples using the Math object can be found in "The Math Object" section of Chapter 5, "Built-In JScript Objects," p. 128.

Listing 4.15 mathex.js--Three Useful Functions Using the Math Object


/* Compute the area of a circle given its diameter */ function areaofcir(diam) { var radius = diam / 2; return( Math.PI * radius * radius ); // pi times r squared } /* Given the coordinates of a point on a circle, determine how far around the circle we must rotate in order to reach that point. Return the angle in radians. */ function angoncircum( x, y ) { var epsilon = 0.00001; // a very small number if ( Math.abs(x) < epsilon ) { // if x is very close to zero

if ( y > 0 ) { // positive x axis return(0.0); // 0 degrees = 0 radians } else { // negative x axis return( Math.PI ); // 180 degrees = pi radians } // end of inner if-else } // end of outer if // division by zero avoided by the "if" test above return( Math.atan( y / x ) ); } /* Given the diagonal size of a television, compute its width assuming that the screen is square */ function tvsize( diag ) { return( diag / Math.SQRT2 ); }

The Date Object


Dealing with dates is one of the most tedious tasks in any language. This is because many humans like to represent dates and times in decidedly nondecimal systems. Months come in units of 12, hours in units of 24, and minutes and seconds in units of 60. All these variations are quite illogical from the computer's standpoint. It likes to deal with nice, round numbers, preferably powers of 2, or at least multiples of 10. The Date object simplifies and automates a lot of the conversion woes associated with going back and forth between a human readable representation, such as Nov 23, 1990, and the internal representation. JScript's Date object follows the UNIX standard of storing date and time information internally as the number of milliseconds since January 1, 1970. This date is often called "The Epoch," because it is shortly after UNIX was first unleashed on an unsuspecting world. CAUTION: The current version of JScript does not permit you to manipulate dates earlier than The Epoch. Attempting to do so gives unexpected and incorrect results.

The Date object has no properties, but many methods. In order to use the Date object, you must first understand how to construct instances of it. There are three basic methods of creating a Date instance, as follows:
q q

new Date() new Date( datestring )

new Date( yr, mon, day )

The first form constructs a Date instance that represents the current date and time. This should be accurate to within a second and also include information about your time zone and any corrections to it currently in effect (such as Daylight Savings Time). The second form takes a string of the form "Month, Day, Year" such as "November 23, 1990" and converts it to a Date instance. This string may optionally have a time of the form HH:MM:SS at the end, which is used to set the time to HH hours, MM minutes, and SS seconds. Hours should be specified using a 24-hour clock, also known as military time, so that 10:15 P.M. is represented as 22:15:00. The third form takes three integers representing the year, month, and day. Note that the month is always indexed from zero, so that November is month 10. The year can also be offset by 1900, so that you can use either of these two forms: var ndat = new Date(90, 10, 23); var ndat = new Date(1990, 10, 23); to create a Date instance named ndat for November 23, 1990. Note that for the year 2000 and beyond, you must use the second form. This form may optionally take an additional three-integer argument for the time, so that 1:05 P.M. on November 23, 1990, is: var ndat2 = new Date(90, 10, 23, 13, 5, 0); The Date object has a large set of methods for getting and setting the components of a date. These methods are as follows:
q q q q q q q q q q q q q q q q

getDate() getDay() getHours() getMinutes() getMonth() getSeconds() getTime() getTimeZoneOffset() getYear() setDate() setHours() setMinutes() setMonth() setSeconds() setTime() setYear()

Most of these methods perform the obvious operation on their Date instance. nvar.getMonth() returns 10, representing November. It is 10, rather than 11, because months are zero-indexed, so that the value of getMonth() is always between 0 and 11, inclusive. The confusingly named

getDate, getDay, and getTime are worth a slightly closer look. The getDate method returns the day of the month (1-31), the getDay method returns the day of the week (0-6), and the getTime method returns JScript's internal representation of the date, namely the number of milliseconds since The Epoch. This last method might seem to be of dubious utility, but it is useful for comparing two dates to see which is later. The set methods are, of course, used to set the various components of a Date instance. Listing 4.16 shows two simple date manipulation functions. This code can be found in the CD-ROM file datex.js.

Listing 4.16 datex.js--Two Useful Functions Using the Date Object


/* Given a date as a string, return the day of the week as an integer between 1 and 7. Note Sunday = 1. */ function dayofweek( datestr ) { var dati; dati = new Date( datestr ); // make datestr into a Date instance return( 1 + dati.getDay() ); // get the day of the week and add 1 } // since getDay() returns a number between 0 and 6 /* Compute the number of days to your birthday. Your birthday is specified as the day and month. Note that your birthday is assumed to occur at midnight, so that if today is your birthday it will be reported as a year away.*/ function tobday( dayi, moni ) { var today, todayy, todayms; var you, youms; var tdiff; today = new Date(); // today's date todayy = today.getYear(); // current year you = new Date(todayy, moni-1, dayi); // your birthday this year // need to subtract 1 because months are zero-indexed todayms = today.getTime(); // convert today to ms since The Epoch youms = you.getTime(); // convert your birthday to ms since The Epoch if ( youms < todayms ) { // if your birthday has already passed.. you.setYear(1 + todayy); // look forward to next year youms = you.getTime(); // recompute ms since The Epoch } tdiff = youms - todayms; // number of milliseconds until your next birthday tdiff /= 1000; // convert to seconds

tdiff /= 60; // minutes tdiff /= 60; // hours tdiff /= 24; // convert to days return( Math.round( tdiff ) ); // round to nearest integer } In addition to the get and set methods, the Date object also has methods for converting a Date instance to a string, and two static methods for parsing dates. These methods are as follows:
q q q q q

toGMTString() toLocaleString() toString() parse( datestr ) UTC( datestr )

The first three of these methods convert a date instance into a string representing the date and time relative to Greenwich Mean Time (GMT, also called UTC for Universal Coordinated Time), relative to the current date formatting conventions (which vary between Europe and the U.S., for example), and as just a plain, ordinary string, respectively. The last two methods are used for converting date strings in local time (parse method) or in UTC time (UTC method) into the number of milliseconds since The Epoch. These methods must be referenced as Date.parse() and Date.UTC() because they are static; they may not be used with Date instances. Because they return the internal representation of dates, these values are often simply passed to setTime. The methods of the Date object are explored more thoroughly in the last two sections of Chapter 5, "Built-In JScript Objects." Troubleshooting: I have modified your function tobday in Listing 4.16. My version accepts an arbitrary string as the input birthday. It works perfectly for my birthday, but it fails horribly for my father's birthday. What is wrong? The code looks like: function tobday2( bdaystr ) { var bdayint = new Date( bdaystr ); ... many lines of code not shown Because your father was undoubtedly born before January 1, 1970, the very first line attempts to create a Date instance corresponding to a date before The Epoch. This is not currently permitted. Because it seems that you were born after The Epoch, the code will work fine for your birthday. Until this restriction is lifted, you must convert the year to one after 1970 before you construct a Date instance, or simply omit the year entirely.

The Array Object


The array object is an extremely simple built-in object which is used to construct an array of empty slots. Any instance of the Array object will always have a length property, and will also have as many elements as are specified in the constructor. For example, the statement: var myarr = new Array(10); constructs an array instance named myarr. The value of myarr.length with be 10, and the properties myarr[0] through myarr[9] will all be NULL. The array object can often be used as a simple object creation function when the values in the array are going to be initialized later. One of the most convenient things about this built-in object is the fact that it always creates a length property.

Built-In Functions
You have now had your first exposure to the built-in String, Math, and Date objects. Some of these objects are more built-in than others. While Date acts like an actual object, with the exception of its two static methods, the String object is almost invisible. All normal JScript programs manipulate strings as if they are a separate data type. The essence of a string is part of the JScript language. There is also a small set of functions built into JScript itself. They are not methods, and are never applied to an instance using the dot operator (.). They are on the same plane as functions that you create using the function keyword. At present, there are five such built-in functions, which are as follows:
q q q q q

escape( str ) eval( str ) parseFloat( str ) parseInt( str, radix ) unEscape( str )

The escape and unEscape functions are used to convert to and from the escape code convention used by HTML. In HTML, a number of special characters, such as the HTML delimiters < and >, must be represented in a special way to include them in ordinary text. For example, if you have written any HTML at all, you know that you sometimes need to type %20 to represent a space character. The escape built-in function takes a string representing one of these special characters and returns its escape code in the form %xx, where xx is a two-digit number. Thus, escape(" ") returns %20, the code for a space character. The unEscape function is the inverse of the escape function. It takes an escape code and returns the character that that code represents. Thus, unEscape ("%20") returns the string " " (a single space character).

The parseFloat built-in function attempts to parse its string argument as a floating-point number. It continues parsing the str only until it encounters a character that could not possibly be part of a valid floating-point number, such as g. The parseInt built-in function performs a similar operation. It attempts to parse its str argument as an integer in base radix. Thus, we would obtain the following values: parseFloat("+3.14williamtell5") = 3.14 parseInt(10111, 2) = 23 Note that everything after the first w is ignored, because w cannot possibly be part of a floating-point number. The second value is obtained because 23 in binary (base 2) notation is 10111. Finally, the eval function attempts to evaluate its string argument as a JScript expression and return its value. All the normal rules for evaluating expressions, including variable substitution, are performed by the eval function. This function is extremely powerful simply because it evaluates any JScript expression, no matter what that expression does. You will see a lot more of this function in several subsequent chapters. For the moment, we briefly look at a simple example in which we ask eval to do some arithmetic for us. If x is a var with the value of 10, then the following two expressions assign 146 to both y and z: y = ( x * 14 ) - ( x / 2 ) + 11; z = eval("( x * 14 ) - ( x / 2 ) + 11");

Browser and HTML Objects


The JScript object model and its very interesting set of built-in objects, methods, and functions provide what we would expect from any modern programming language. They provide control structures, encapsulation, functions, mathematical operations, and so forth. Since JScript is designed to work with and on the World Wide Web, there must also be a linkage between it and the contents of HTML pages. This linkage is provided by JScript's extremely rich set of browser and HTML objects. The browser objects are a reflection of the browser environment, and include objects that can be used to reference the current page, the history list, and the current URL. There are also methods for opening new windows, putting up dialog boxes, and writing HTML directly. We have already been leaning heavily on one such method, the write method of the document object. The browser (or navigator) objects are at the top of JScript's object hierarchy, because they represent overall information and actions that are not necessarily associated with a particular Web page. Within a given Web page, however, each HTML element has a corresponding object, an HTML object, within the object hierarchy. In particular, every HTML form, and every HTML element within every form, has a corresponding object. Figure 4.5 gives an overview of the JScript object hierarchy.

Figure 4.5 JScript browser and HTML objects refer to all elements of a Web page. In this section, we briefly describe the key JScript browser and HTML objects, and show how they relate to one another. Most of the subsequent chapters in this book are devoted to in-depth discussions of how you can make these objects work for you. Each chapter in Part II, "JScript Objects," in fact, is devoted to a particular category of JScript object (built-in, browser, or HTML). The purpose of this section, then, is to acquaint you with the structure of these objects without going into too much detail on how they are used.

Browser Objects
The primary browser objects, in rough order of significance, are as follows:
q q q q

window document location history

The window Object. The window object, as Figure 4.5 shows, is the top object in the JScript object hierarchy. Every browser window that is currently open will have a corresponding window object. All the other objects are children of one of the window objects. In particular, every window is associated with a particular Web page, and the HTML structure of this page is reflected in the window's document object. Every window corresponds to some URL; that URL is reflected in the location object. Every window has a history of the previous pages that have been displayed in that window, which are represented by the various properties of the history object. There are several special window objects worth noting. The top window refers to the highest-level window on the current Web page. The self window refers to the current window, while parent refers to that window's parent, if any. JScript tries to keep track of the current window, so that almost all references to subobjects of the current window do not need to refer to self explicitly. This is why all of our output has been done using document.write() rather than self.window.write () or window.document.write(). window objects have the following interesting methods (among others):
q q q q q

alert( msgstr ) close() confirm( msgstr ) open( urlstr, wname ) prompt( msgstr )

All these methods are used to manipulate the window state of the browser itself. The alert and confirm methods are used to display their msgstr argument in a dialog box. The alert method is used to alert the user to something about which the user can do nothing. An Alert dialog box contains a single OK button. The Confirm dialog box is more flexible, and displays its message

with both an OK and a Cancel button. If the user selects OK, the confirm method returns true; otherwise, it returns false. The prompt method is used to solicit user input in the form of a string. It displays a dialog box with the msgstr and an editable text field. This method also accepts a second optional argument that can be used to set a default value in the input field. This method returns whatever the user typed as a string. You use the open method of the window object when you wish to open a new browser window. The urlstr argument is a string representing the URL that will be loaded into that window. The wname argument is a string that gives the new window its name. This method returns an instance of the window object representing the new window created. This method also accepts a third argument that can be used to specify a wide variety of display options for the new window (such as whether or not it should display its toolbar). When the close method is invoked from a window instance, the underlying window is closed and the URL in it is unloaded. Several excellent examples of the open and close methods can be found in the "Dynamic Documents" section of Chapter 8, "Dynamic HTML and IE Objects." The document Object. Every window is associated with a document object. The document object contains properties for every anchor, link, and form on that page, as well as all of the subelements of those elements. It also contains properties for its title (the content of the <TITLE> field of the page), its foreground color (the fgColor property), its background color (the bgColor property), its various link colors, and other attributes of the page itself. The document object has the following methods:
q q q q q

n clear() close() open() write( str ) writeln( str )

The clear method is used to completely erase a document window. The entire contents are wiped out, regardless of how they got there. The clear method is particularly useful if you are constructing a Web page entirely within JScript, and want to make sure it is empty before you start. The open and close methods are used to start and stop buffered output. If you call the open method, perform a series of writes or writelns, and then call the close method, the results of your write operations are laid out and appear on the page.

CAUTION: Do not confuse the open and close methods of the document object with the window methods of the same names. They perform very different functions, and are not interchangeable. Use an explicit reference--document.open() or window.open ()--to obtain the appropriate one.

Of course, we are intimately familiar with the write method by now. The write method is used to write any string expression, including one containing embedded HTML, to the current document. Note that the write method actually takes a variable number of arguments, rather than just one. If more than one argument is given, each of the arguments is interpreted as a string and written in turn. The writeln method is identical to the write method, except that it outputs a carriage return after it has completed writing its argument(s). Note that this carriage return will be ignored by HTML, which really does not like embedded white space, unless the writeln is inside preformatted text (within <PRE>...</PRE> tags).

NOTE: Internet Explorer 3.0 has a bug in the implementation of document.write() and document.writeln(). The output of these functions is not appended at the end of the current document. A new document is always created, and the output written there. In addition, if no document.close() is used after a write operation, it may be necessary to press the Stop button on the IE toolbar to close the document.

The history and location Objects. The history object is used to refer to the history list of previously visited URLs. The history object has a property known as length, which indicates how many URLs are stored on the history list at present. It also has the following three methods:
q q q

back() forward() go( where )

The go method is used to navigate the history list. The where argument is a number that indicates how far we want to move in the history list. A positive number means that we want to move that many documents forward in this history list, while a negative number is used to move backward. Thus, go(5) has the same effect as using the Forward button five times, while go(-1) would be the same as clicking the Back button once. The location object describes the URL of a document. It has properties representing the various components of the URL, including its protocol part, its hostname part, its pathname part, and its port number part, among other properties. It also has a toString method that can be used to convert it to a string. We can use the following code to display a formatted message giving the current URL: var loc = document.location; document.write("<BR>URL is " + loc.toString()); document.write("<BR>");

HTML Objects
To understand how HTML objects work in JScript, let us consider a simple piece of HTML that

creates an anchor, a small form, and a link to that anchor. This is not intended to be the HTML for a meaningful Web page, but it will nevertheless illustrate the correspondence between HTML elements and JScript HTML objects. Our elementary HTML code is given in Listing 4.17. This code can be found in simple4.htm on the CD-ROM.

Listing 4.17 simple4.htm--HTML Code for a Page with a Form, Anchor, and Link
<HTML> <HEAD> <TITLE>A very simple HTML page</TITLE> </HEAD> <BODY> <A NAME="top">This is the top of the page</A> <HR> <FORM METHOD="post" ACTION="mailto:nobody@dev.null"> <P>Enter your name: <INPUT TYPE="text" NAME="me" SIZE="70"> </P> <INPUT TYPE="reset" VALUE="Oops"> <INPUT TYPE="submit" VALUE="OK"> </FORM> <HR> Click here to go to the <A HREF="#top">top</A> of the page </BODY> </HTML> This code creates an HTML page with an anchor at the top of the page and a link to that anchor at the bottom. In between is a simple form that allows the user to enter his or her name. There is a Submit button for if he gets it right, and a Reset button for if he doesn't. If the user is successful, the form's contents are submitted via a post action to the fictitious e-mail address nobody@dev.null. The important aspect of this example is not its primitive HTML, but the fact that the HTML elements in it are reflected in the JScript object hierarchy. We have already seen that we can access the title of this document through the title property of the document object. We can also access the other HTML elements of this document using the following properties:
q q q

anchors forms links

These properties of the document object are arrays representing every HTML element that is an anchor, form, or link on the page. In our particular example, there is only one of each, so we would refer to the anchor at the top of the page as document.anchors[0], the link at the bottom of the page as document.links[0], and the form in the middle of the page as document.forms [0]. These are the top-level HTML objects represented by this document. Each of these elements, in

turn, has properties and methods that can be used to describe and manipulate it. In particular, the form object corresponding to forms[0] has subobjects for each of the three form elements (the Reset button, the Submit button, and the text input field), as well as properties for the submit method and the submit target. forms[0].elements[0] corresponds to the text input field. forms[0].elements[0].name is the name of that field, as specified by the NAME field, which is "me" in this case. Figure 4.6 recapitulates this HTML code and shows how each element in the page is associated with an HTML object. We will have many more examples of this in subsequent chapters. Figure 4.6 Anchors, links, forms, and form elements are represented as objects in JScript.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Chapter 2 JScript: The Language


q

JScript: The Language r JScript Syntax r Variables and Values s Implicit Data Types in JScript s Type Conversion r Statements and Operators s The Structure of JScript Statements s Operators s Comments in JScript Code r Control Structures s The if Statement s The while Statement s The for Statement r Functions and Objects s Functions s Objects

JScript: The Language


q q q

Use operators and expressions Manipulate data types and literals Manage the flow of control in several ways

Define JScript functions There are many, many different computer programming languages in use today. Each has its own set of special features, which are highly praised by its fans and vigorously panned by its detractors. If you have worked in more than one language, you are aware that there is a continuum of language styles, ranging from highly structured languages, such as Ada, to more freewheeling ones, such as LISP. Many are associated with specific settings or applications. Ada, for example, is often found in military projects, while LISP is often associated with artificial intelligence. Some languages, such as HTML, the language used to describe the layout of World Wide Web pages, have a well-defined organizational structure, but have very little in the way of traditional program structure (there are no data types, for example). In trying to understand a new language, it is not only important to master its syntax, it is also vital to appreciate its style--the way in which that language can be used to accomplish specific goals. We

have already reviewed the basic goals of JScript in Chapter 1, "What Is JScript?" as well as contrasting it to the more structured Java language. This chapter describes the JScript language from both perspectives. A thorough description of its syntax is given, and some initial concepts on how to structure a JScript program are also introduced. Anyone who has programming experience in almost any modern declarative language, such as C, C++, Perl, or Pascal, will immediately feel at home. In addition, HTML authors who have never programmed will be able rapidly to acquire JScript proficiency.

JScript Syntax
JScript is based on an action-oriented model of the World Wide Web. Elements of a Web page, such as a button or check box, may trigger actions or events. When one of these events occurs, a corresponding piece of JScript code, usually a JScript function, is executed. That function, in turn, is composed of various statements which perform calculations, examine or modify the contents of the Web page, or perform other tasks in order to respond in some way to that event. For example, pressing the Submit button on an online order form might invoke a JScript function that validates the contents of that form to ensure that the user entered all the required information. In this section, we examine the syntax of JScript from the bottom up. We begin with the most basic concepts of how to write a JScript statement and what that statement does, and progress upward through more complex and powerful structures in subsequent sections, culminating in a detailed discussion of JScript functions and related concepts. Chapter 3, "Events and JScript," explores in greater detail how these elements are tied into Web pages through events. In general, the elements of a JScript program can be divided into five categories, as follows:
q q q q q

Variables and their values Expressions, which manipulate those values Control structures, which modify how statements are performed Functions, which execute a block of statements Objects and arrays, which are ways of grouping related pieces of data together

This set of categories is very similar to many other languages. As we examine each of these elements in subsequent sections, we will discover that JScript is somewhat minimalist in its approach. Many familiar elements, such as explicit data types (int, String, REAL), are missing or have been substantially simplified. However, JScript also provides a number of powerful object-oriented constructs which greatly simplify program organization. In this way, JScript has the expressive power of languages such as C or Java, while also having fewer rules to remember.

Variables and Values


One of the main differences between JScript and most other languages is that it does not have explicit data types. There is no way to specify that a particular variable represents an integer, a string, or a floating-point (real) number. Any JScript variable can be any of these--in fact, the same variable can

be interpreted differently in different contexts. All JScript variables are declared using the keyword var. A variable may be initialized, meaning that it is given a value when it is declared, or it may be uninitialized. In addition, multiple variables can be declared on the same line by separating their names with commas. For example, the statements: var x = 7 var y,z = "19" var lk = "lucky" declare a variable named x with initial value 7, an uninitialized variable y and variables named z and lk whose initial values are "19" and "lucky," respectively. It might seem that x is an integer, z and lk are strings, and y is some undefined quantity. In fact, the real story is a little more complicated than this. The value of each variable depends on the context in which it is used. This context is related to the order in which the variables are seen. As you might guess, the expressions: 5 + x lk + z evaluate to 12 and "lucky19," seemingly confirming our suspicions about what they really are. However, it is also possible to form the expressions: lk + x x + z which evaluates to "lucky7" and 26, respectively. In the first expression, x has been interpreted as a string, while in the second, z has been interpreted as an integer.

TIP: JScript often attempts to treat all variables within a statement as if they had the same type as the first variable in the statement.

These examples illustrate two critically important points about the JScript language. First, while JScript does not have explicit data types, it does have implicit data types. Second, JScript has a set of conversion rules that allow it to decide how to treat a value based on the context in which it is used. The context is established by reading the expression from left to right. In the expression x + z, for example, x is implicitly a numerical value, so that JScript also attempts to view z as a number and perform the sum numerically. It succeeds, and the expected 26 results. What would have happened if we had tried x + lk? The x variable occurs first on the left, and is really a number at heart. JScript thus tries to interpret the variable lk as a number, too. This is extremely unlucky, in fact, because "lucky" cannot be converted to a number (while z, the string "19" could). JScript reports an error if asked to evaluate x + lk. To understand JScript variables and values, therefore, it is necessary to understand its set of implicit types and how they may be converted

to one another. Before we enter into these details, let us consider one final example. In all the preceding cases, the uninitialized variable y was never used. What would be the value of an expression such as: x = z + y Of course, as in all other programming languages, the result of using an uninitialized variable is never good. Since y has never been given a value, there is no way this expression can be evaluated. It may result in something seemingly innocent, such as x being assigned the value of z, as if y were zero. It may also result in something much more serious, such as the value of x becoming something strange, or, more likely, a JScript error occurring. This leads to the following commonsense rule.

TIP: Initialize all JScript variables to meaningful default values. If a variable has no meaningful default, initialize it to null.

Implicit Data Types in JScript


There are five major implicit data types in JScript. A JScript value may be as follows:
q q q q q

A number, such as -5, 0, or 3.3333 A string, such as "Click Here" or "JScript" One of the logical values true or false A "nonatomic" JScript element, such as a function or object The special value null

Actually, it would be more correct to say that there are five categories of data type, because it is possible to distinguish two different types of numbers (integers and floating-point numbers), and many different types of JScript objects, functions, and other structured types. In fact, Part II of this book, "JScript Objects," is entirely devoted to explaining the many different JScript objects. Variables and Variable Names. It is very important to distinguish between variables and their values. The statement x = 10 contains two components: the variable x and the literal value 10. A literal refers to anything that is referred to directly by its actual value. A variable is just an abstraction that provides a way of giving names to values. Thus, the statement x = 10 says, "I am going to refer to the concrete (literal) quantity 10 by the abstract (variable) name x," just as you might say, "I am going to call this lumpy thing I'm sitting on a chair." This also leads to the following important piece of advice.

CAUTION: It is bad practice to change the implicit data type of a variable. If a

variable is initialized to have a certain type (such as string), it should always have that type.

Thus, because we have started out with x = 10, we should make sure that x always has some numeric value. There is no rule that prohibits us from later saying x = "Fortran," but this will generally lead to confusion or programming errors in most cases. No one will stop you from calling that lumpy thing you are sitting on "bacon and eggs," but many of your guests may become confused if you do so. One final rule about variable names: A valid JScript variable name must begin with a letter or with the underscore character (_). Case is important, so that norl, NoRl, NORL, and _NORL are all valid JScript variable names that refer to different variables. Numerical Values. There are two numeric types in JScript: integers and floating-point numbers. The rules for specifying both types are almost identical to those of C or C++ or Java. Integers may be specified in base 10 (decimal), base 8 (octal), or base 16 (hexadecimal) formats. The three forms are distinguished as follows, based on the first one or two characters:
q q q

1-9 followed by any set of digits is a decimal integer. 0 followed by any set of the digits 0-7 is an octal integer. 0x or 0X followed by any of 0-9, a-f, or A-F is a hexadecimal integer.

Any of the three forms can also start with a plus (+) or minus (-) sign. Thus, -45 is a decimal integer, 017 is an octal integer, and 0x12EF5 is a hexadecimal integer. The minimum and maximum integers that can be used are implementation-dependent, but at least 32 bits should be expected. Floating-point numbers can be specified in either the standard decimal point (".") format or the engineering E-notation. Typical floating-point numbers should contain a decimal point or an exponent, which may begin with either e or E. A floating-point number may also have a + or - sign. So 0.0, -1.4e12, and 3.14159 are all valid floating-point numbers. The range of valid floats is again implementation-dependent, but you should expect that any valid, short, floating-point number, as defined by the IEEE standard, is acceptable. (The IEEE is the Institute of Electrical and Electronics Engineers, a professional and standards-making organization.) Note that the original LiveScript language, as well as early versions of JavaScript for Netscape, attempted to treat all the numeric types the same. Because it has become JScript, there has been a convergence toward the numerical types of the Java language, and the distinction between integer values, such as 5, and floating-point (or real) values, such as 3.3333, has increased.

CAUTION: LiveScript is now completely obsolete. It has been replaced by its descendants, JavaScript, and JScript. Avoid any code you encounter that is labeled as LiveScript, as

it will almost certainly not work correctly.

NOTE: Watch out for changes in the way JScript handles numeric types. In the future, the distinction between integers, single-precision floating-point types (floats), and doubleprecision floating-point types (doubles) may become much sharper.

Strings. In JScript, strings may be specified using either single quotes (`stuff') or double quotes ("otherstuff"). If you begin a string with one type of quote, you must end it with that same form of quote--for example, "badstuff' is not a legal string in JScript. Strings may also be nested by alternating the types of quotes used. In fact, you must alternate single and double quotes if you wish to put one string inside another. Here is an example of several nested strings: "Oh, it's `Tommy this' and `Tommy that' and `throw 'im out, the brute'." As in C and Java, JScript strings may contain special combinations of characters, known as escape sequences, to denote certain special characters. The rules for this are still emerging, but it is probably safe to assume that all the escape sequences defined in C will be supported. Because you will almost always be using formatting directives of HTML (such as <BR> for a line break) you will probably not use these directives very often. At the moment, the following sequences are supported: \t tab \r line feed \n return \f form feed (vertical tab) \b backspace See the "Manipulating Text Fields" section of Chapter 6, "Interactive HTML Objects," for more information on combining HTML directives with text. The special string "" or `' represents the zero-length string. This is a perfectly valid string whose length is zero. This is the shortest JScript string; the length of the longest is, as usual, implementationdependent. It is reasonable to expect that most JScript environments will permit very long poems (or very short legislative measures) to be represented as single strings. Logical Values. The logical, or Boolean, values true and false are typically used in expressions that test some condition to determine how to proceed. If that condition is met, one set of statements is executed; if it is not, another set is used instead. The first corresponds to the true condition, whereas the second represents the false condition. Not surprisingly, such expressions are known as conditional expressions. As you will see in the following section on "Operators," there are several comparison operators, such as the equality test (==), which result in logical values. It is possible to think of true as 1 and false as 0. In fact, JScript often converts these logical values into 1 and 0, respectively. JScript also accepts any non-zero integer in place of true, for example, so

that 5 and -3 can both be used as stand-ins for true. Many different programming languages follow this same convention. It should be avoided in JScript, as it can lead to type confusion. The Value null. The value null has a very special role in the JScript language. It is the value of last resort, so to speak, for every variable. For the beginning JScript programmer, its primary role will be in initializing variables that do not have any more meaningful initial value. For example, in the set of variable declarations given in the preceding section on "Variables and Values," to initialize y to some value, we should have actually written: var y = null This prevents JScript errors that arise when an uninitialized variable is accidentally used in an expression that requires a value. It is important to realize that the value null does not give the variable y any implicit data type. null also has the property that it may be converted to a benign form of all the other types. When it is converted to a number, it becomes 0; when it is converted to a string, it becomes the empty string ""; and when it is converted to a Boolean value, it becomes false. This is the one case where it is permissible to change the implicit data type of a variable after it is declared. Therefore, statements such as: var lk2 = lk + y var w = x + y result in lk2 having the value "lucky" (the same as lk) and w having the value 10 (the same as x). This is why the value null is an excellent way of initializing variables--it is guaranteed to be harmless.

Type Conversion
Several of the examples in the previous section use the + operator to combine different types of things. You may recall that when a string is combined with a number in the form: stringthing + numberthing the number is converted to a string and the + operator then glues the two strings together (known as concatenation). However, if they are combined in the opposite order: numberthing + stringthing then JScript attempts to convert the stringthing to a number and add it, numerically, to numberthing. If the stringthing can be converted to a string, such as "-14," then all goes well; if it cannot, an error results. This illustrates the concept of implicit conversion in JScript.

We have already seen that some examples of implicit conversion are completely safe. false can be converted to 0, "5" can be converted to 5, and null can be converted to just about anything. However, some conversions are obviously invalid, and others might be questionable. Questions such as: "May the string `3.0' be legitimately converted to the integer 3?" are actually very difficult to answer with complete generality. There are two approaches to handling this complex issue: Use explicit conversion whenever possible, and use implicit conversion with great care. A detailed study of explicit conversion is in Chapter 5, "Built-In JScript Objects," beginning with the section, "The String Object." For the moment, we will use the following rules of thumb. See the "The String Object" section of Chapter 5, "Built-In JScript Objects," which discusses the rules for string-to-number and number-to-string conversion, the source of most conversion errors in JScript.

CAUTION: Use implicit conversion only when converting to a string form. Never use it to convert to numerical form. This is because attempts to convert a non-numerical quantity to a numeric form cause serious JScript errors, while conversion to string form generally do not.

You have probably already noticed that conversion to a string is always safe, at least for the data types we have encountered so far. In fact, this type of implicit conversion is a boon to the JScript programmer, since it avoids the tedious formatting directives that are necessary in many languages such as C. In JScript, we can say: "This page has been accessed " + cnt + " times today" without having to worry about the data type of the variable cnt. This construction will always give a valid string, and never an error. The preceding Caution is also based on standard principles of defensive programming. There are many things that cannot be sensibly converted to a numerical form, so the prudent approach is never to try to implicitly convert anything to a number. There are several more robust approaches that can be used in case we have a string that we want to convert to numerical form. These are described in Chapter 5. We will also see other exceptions to this rule as our mastery of JScript deepens.

Statements and Operators


The basic unit of work in JScript is the statement, as is the case in most programming languages. A JScript statement accomplishes work by causing something to be evaluated. This can be the result of

giving a value to a variable, by calling a function, by performing some sort of calculation, or any combination of these. We have already seen variable declaration statements, which not only create (declare) a new variable, but also give it an initial value, such as the following statement: var x = 10 JScript programs, as mentioned at the beginning of this chapter, are collections of statements, typically organized into functions, which manipulate variables and the HTML environment in which the script itself works, in order to achieve some goal.

The Structure of JScript Statements


Before plunging into a detailed description of the various types of statements and the operators they use, let's examine one simple statement in excruciating detail. Consider the statement: y = x + 5 This statement contains three parts: the result y, the operator =, and the expression x + 5. The result always occurs on the left side, because JScript always operates from left to right, and is often called the lvalue. The result must always be something that can be modified. It would be erroneous to write null = x + 5, for example, because null is a built-in, unchangeable component of JScript itself--it cannot be modified, so it can never appear as a result. The operator = is the assignment operator, of course. It causes the expression on the right to be evaluated and its value given (assigned) to the result. The expression x + 5 contains another operator, the + operator, which acts to combine x and 5 in some context-specific way. Since x is a number in this case, the + operator performs ordinary addition, and y gets the value 15. As we have already seen, if x had been a string, such as "bleh," then + would have acted as a string concatenation operator and y would be given the value "bleh5" instead. This is an example of operator overloading--the + operator can do different things in different situations. Several JScript operators are overloaded. There is one final point to be made about this statement, and about the structure of JScript programs in general. JScript has adopted a line-oriented approach to program flow. This means that it knows that a statement has ended when it reaches the end of a line. It is also possible to explicitly terminate a statement with a semicolon character (;). The statement y = x + 5; is identical in effect to the statement y = x + 5. This also means that you can, in fact, put multiple statements on a single line by separating each of them with a semicolon. For those just starting out in JScript, it is often a good idea to terminate each statement with a semicolon, and also to put only a single statement on each line. This might seem both redundant and extraneous, but it is well justified. The end of a line is often a purely visual concept. Anyone who has ever used a word processor has undoubtedly encountered the situation where a very long line looks like two lines. Different platforms (PC, Macintosh, UNIX) also have their own unique ideas as to what the proper end-of-line characters are. It is much safer to put in the extra semicolon character and

be explicit about the end of the statement than it is to rely on one's eyesight.

Operators
The set of operators that JScript uses is, once again, very similar to that of the C, C++, and Java languages. It provides a number of different ways of combining different values, both literals and variables, into expressions. Some operators require two elements to participate in the operation, and are referred to as binary operators. The + operator is a binary operator. Other operators require only a single participant (operand), and are known as unary operators. The ++ operator, which adds 1 to its operand, is a unary operator. Operators may also join forces to form aggregate operators, as we shall see next. JScript operators may be classified into the following groups:
q q q q

Computational operators Logical operators Bitwise operators Assignment and aggregate operators

This grouping is purely functional, and is based on what the operators actually do. The next four subsections examine each type of operator in more detail. Table 2.1 summarizes the operators in each category and how they are used. Table 2.1 A Summary of JScript Operations Symbol + * / % ++ -Computational Operators Addition, String Concatenation Subtraction, Unary Negation Multiplication Division Modulus Preincrement, Postincrement Predecrement, Postdecrement Logical Operators ==, != <,<=,=>,> ! &&,|| ? Equality, Inequality Arithmetic and String Comparison Logical NOT Logical AND, Logical OR Conditional Selection (trinary)

Logical Concatenation Bitwise Operators

&,| ^ ~ <<,>>,>>>

Bitwise AND, Bitwise OR Bitwise exclusive OR (XOR) Bitwise NOT Shift Left, Shift Right, Unsigned Shift Right Assignment Operators

= OP=

Assignment Aggregate Assignment (+,-,*,/,%,&,|,^,~,<<,>>,>>>)

Computational Operators. The computational operators are addition (+), subtraction and negation (-), division (/), multiplication (*), modulus (%), increment (++), and decrement (--). These operators are often used in performing arithmetic computations, but do not forget that the + operator is overloaded; it also has the extremely important role of string concatenation. The first five computational operators have their standard mathematical meanings. They add, subtract, divide, or multiply two numeric quantities. By combining two quantities using one of these operators, the result is made as precise as possible. If an integer is added to a floating-point number, the result is a floating-point number. The following four statements illustrate the use of these operators: x = 4 + y; y = 5.5 - z; z = 10 / w; w = 1.4e5 * v; Note that division of integer quantities returns a result which is as precise as possible, so that if w had the value 4 in the third statement, z would get the floating point value 2.5, not the integer value 2. Note also that the - operator may also be used as a unary operator to compute the negative of a numeric quantity: n = -m; This has exactly the same effect as if we had multiplied m by -1. The modulus operator (%) is used to compute the remainder from a division. Although it can be used with floating-point numbers, it is typically used with integers, so that 21 % 4 evaluates to 1. The modulus operator always gives a remainder that has the same sign as the corresponding quotient, so that -21 % 4 evaluates to -1, not 3. The increment and decrement operators are conveniences created to simplify the very common operations of adding or subtracting one from a number. Both these operators are unary and come in two forms: prefix and postfix. The expression ++x is the preincrement form of the ++ operator, while x++ is the postincrement form. This leads to a subtle and often misunderstood point about the

increment and decrement operators. Supposing that x has its usual value 10, consider the two statements: y = ++x; z = x++; These look very similar, but are in fact very different. After both of these statements have been executed, x has the value 11. However, y ends up with the value 11, while z has the value 10. Why? The reason has to do with the complex issue of in what order the operators ++ and = are evaluated in these two statements. In the first statement, the ++ is evaluated first, so that x attains the value 11, and then the assignment = is evaluated, so that this value is passed on to y. In the second statement, the assignment operator = is applied first, so that z becomes 10, the current value of x, and then the + + is applied to x, so that it advances to 11. The same rule applies to the decrement operator (--). This might seem like it is a violation of the rule of left-to-right evaluation, and it is. Even though the equals sign is to the left of the preincrement operator (++) in the first statement, the ++ operator takes effect first. This is an example of operator precedence, the order in which multiple operators are applied. This complex topic is discussed in more detail in the "Order of Evaluation" section later in the chapter.

NOTE: Internet Explorer 3.0 has a bug in its order of evaluation. The right side of an expression is always evaluated completely before the assignment takes place. In IE3.0, both y and z will have the value 11.

Logical Operators. Logical operators in JScript are used either to carry out some form of test, or to combine the results of more than one such test. They are often referred to as conditional operators. The logical operators that perform a test of some sort are the equality/inequality operator (== and ! =), the comparison operators (<, <=, >, and =>), and the logical negation operator (!). The operators that combine logical values are logical AND (&&) and logical OR (||). Finally, the conditional operator (?) and the comma operator (,) are also combining operators, although they are only vaguely logical operators. Equality Operators. The binary equality (==) and inequality (!=) operators are used to test if two quantities are the same or different. These operators are overloaded. On integers, they test for strict equality or inequality. On floating-point numbers, they test to see whether the two quantities are equal within the precision of the underlying floating-point type. On strings, they test for exact equality--recall that case is significant in JScript strings. These operators all return a Boolean value, either true or false. For example, if x has the value 10, y has the value 3.0, and z has the value "barney," then x == 10 is true, y != -5.0 is also true, and z == "fred" is false. Unfortunately, even operators as simple as these can be a source of error. It is regrettable that the

logical operator == looks so much like the assignment operator =. Consider the following incorrect code fragment: if ( x = 3 ) { stuff... The purpose of this code is almost certainly to test the value of the variable x against the constant 3, and to execute the "stuff" if that test succeeded. This code fails to realize that purpose in two very dramatic ways, just by inappropriately using = instead of ==. First of all, x = 3 always gives x the value 3, no matter what its previous value was. Instead of testing x using ==, we have altered it with =. Second, the value of the expression x = 3 is the value of its left side, namely 3. Even though 3 is not a true logical value, it is treated as true by the if statement (if is described in greater detail in the section "Control Structures" later in this chapter). This means that "stuff" will always be executed, rather than being executed only when x has the prior value 3. This type of error occurs in every programming language in which similar operators are used for very different purposes. In this case, we could have adopted another rule of defensive programming and said: if ( 3 = x ) { stuff... In this case, our typing mistake (= instead of ==) leads to an error, rather than resulting in a subtle programming flaw. Since 3 is a constant, it can never appear on the left side of an assignment, but it is quite capable of appearing on the left side of a logical test. Said another way, since x == 3 and 3 == x are completely equivalent, the form 3 == x is preferable. If it is mistyped as an assignment statement (3 = x), it leads to an immediate error, rather than one that might take hours of debugging to uncover. This leads to the following advice.

TIP: When testing for equality, always put constants on the left, especially null.

There is another subtle evil about the (in)equality operators when they are used with floating-point numbers. It is very tricky to make floating-point arithmetic completely independent of the underlying machine. This means that z == 3.0 might be true on one machine but false on another. It can also lead to seemingly absurd results such as 3. == 3.00 being false while 3.0 == 2.9999999 is true. A remedy for this problem is presented at the end of this section. Comparison Operators. The comparison operators (<, <=, >, and >=) also operate on both numbers and strings. When they act on numbers, they perform the usual arithmetic comparisons,

yielding Boolean values, as with the equality operators. When they act on strings, they perform comparisons based on dictionary order, also known as lexicographic order. If a string str1 occurs earlier in the dictionary than a second string str2, then the comparison str1 < str2 (and also str1 <= str2 ) will be true. For example, "barney" < "fred" is true, while "Franklin" < "Delano" is false. The Negation Operator. The logical negation operator (!) is used to reverse the sense of a logical test. It converts true to false and false to true. If x < 15 is true then !(x < 15) is false, and vice versa. Note that ! may also be used with integer values, so that !0 is true, while ! 5 is false. As in other cases, this use of the ! operator violates type boundaries and should be avoided. Boolean Logical Operators. The logical AND (&&) and OR (||) operators are among the most powerful operators in JScript. Both may be used to combine two or more conditions into a composite test. The logical AND of a set of conditions is true only if all of its component conditions are true. The logical OR of a set of conditions is true if any of its component conditions are true. Thus: ( x < 17 ) && buttonPressed && ( z == "Meta" ) is true precisely when x is less than 17 and the Boolean variable buttonPressed is true and z is exactly equal to the string "Meta." Similarly, ( x < 17 ) || buttonPressed || ( z == "Meta" ) is true if one or more of the three conditions is true. Lazy Evaluation. JScript uses a lazy variant of its usual left-to-right evaluation rule with the && and || operators. This lazy evaluation (or short-circuit evaluation) rule states that JScript stops trying to evaluate the expression as soon as its value is known. To see how this works, suppose that x has the value 20, buttonPressed is true, and z is the string "Hyper". Because ( x < 17 ) is false, the second and third conditions in the logical AND statement are never evaluated. This is because false && anything is always false, so the value of the first expression must be false. Similarly, the second statement stops as soon as buttonPressed is evaluated. Since true || anything is always true, the second expression must be true. Lazy evaluation can be both a boon and a curse. Suppose that "digofpi(1000000000)" is a function that computes the billionth digit of pi. The expression: ( x < 25 ) || ( digofpi(1000000000) == 3 ) does not actually try to compute the billionth digit of pi if x is 20, because the expression is already known to be true, and digofpi() is never called. As an additional example, consider the following expression:

( x < 25 ) && beaupage() Suppose that beaupage() is a function that displays a beautiful Web page. If x is 30, this page will never be seen, because the first part of expression ( x < 25 ) is already known to be false. As a result, the function beaupage() is never called. We revisit this phenomenon in the "Functions and Objects" section at the end of this chapter. For the moment, it is wise to be aware of lazy evaluation. Fuzzy Comparison. The logical AND and OR operators also provide us with one solution to the problem of floating-point comparison. While it may not be possible ever to determine whether x is exactly equal to the constant 3.0, you can be certain that it is close using a combined test such as: ( x - 3.0 ) < epsilon || ( 3.0 - x ) < epsilon where epsilon is some suitably small value, such as 0.001. This form of test is often referred to as a fuzzy comparison.

CAUTION: Floating-point arithmetic is not an exact science. Avoid exact comparison tests such as == and !=; use fuzzy comparisons instead.

The Comma and Question Mark Operators. The final two operators in the logical category are the conditional operator (?), often called the question mark operator, and the comma operator (,). These two operators are only vaguely logical, but they don't readily fall into any of the other categories either. The conditional operator is the only trinary (3-operand) operator in JScript. It is used to select one of two possible alternatives based on a conditional test. The syntax for this operator is: ( conditionthing ? truealt : falsealt ) If the conditionthing is true, the value of this expression is truealt; otherwise, it is falsealt. Note that the colon (:) separating the true alternative from the false alternative is mandatory. This can be used to select an appropriate alternative and simplify code, as in this example: printme = ( errorcode == 0 ? "OK" : "error" ); This expression makes the variable printme have the string value "OK" in case the variable errorcode is 0; otherwise, it is set to "error". The question mark operator is often a fast way to select one of two choices when a control structure would be unnecessarily cumbersome. Finally, the lowly comma operator can be used to force the evaluation of a set of expressions. All intermediate results are discarded, and the value of the very last expression on the right is returned.

For example, the expression: b = (d = digofpi(1000000000)), beaupage(), (x < 17); always computes the billionth digit of pi and assigns it to the variable d, always displays the beautiful page, always compares x against 17, and returns only the result of that comparison since x < 17 is the rightmost expression. The result of that comparison is assigned to the Boolean variable b. This might seem like a clever way to outwit JScript's lazy evaluation, but it would be clearer simply to write: d = digofpi(1000000000); beaupage(); b = ( x < 17 ); In general, the comma operator is useful only when it is inside a for loop (see "Control Structures," later in this chapter), and should otherwise be ignored. Bitwise Operators. In many situations, you do not need to know, nor do you want to know, the precise binary representation of values in your program. There are some situations, however, in which it is absolutely essential to operate at the lowest possible level and deal with the individual bits of a particular value. This often arises in mathematical applications, for example, or when precisely manipulating color values. The bitwise operators are used for this purpose. Table 2.2 shows JScript's bitwise operators. Note that all are binary, except for bitwise not, which is unary. Each operates on its operands one bit at a time. Table 2.2 JScript's Bitwise Operators Operator Name Bitwise AND Bitwise OR Bitwise XOR Bitwise Left Shift Bitwise Signed Right Shift Bitwise Unsigned Right Shift Bitwise NOT Symbol & | ^ << >> >>> ~

Bitwise AND (&) examines each bit position in each of its operands. If both operands have a 1 bit in a given position, then that bit will also be set to 1 in the result. In all other cases, the output bit position is zero. For example, suppose x = 0x00001234 and y = 0x8000ABCD. Then z = x & y will have the value 0x00000204. You can see this more easily by writing x and y in base 2 (binary) notation, and looking for those positions in which both x and y are 1, as shown in the first part of Figure 2.1. Figure 2.1

JScript's bitwise operators operate on each bit separately. Note that x and y have only the same bits set in highlighted positions, so that those are the only bits set in their logical AND z. In this way, bitwise AND is the bit level analog of the logical AND. Bitwise OR (|) is similar. If either bit is 1 in any bit position, then that bit will be 1 in the result. Thus, the value of w = x | y will be 0x8000BBFD, as you see in the middle part of Figure 2.1. Each bit is set in w if either or both of the corresponding bits in x and y is set. The bitwise XOR (exclusive OR) (^) operator is a variation on the bitwise OR operator. It sets a bit in the result if either bit in the operand is set, but not both. The value of v = x ^ y is 0x8000B9F9, as shown at the bottom of Figure 2.1. These three operators may also take more than two operands, so that it is possible to write a very long expression such as: n = ( a & b & c & d & e ); which operates from left to right, as usual. This expression takes the bitwise AND of a and b, ANDs that result with c, ANDs that result with d, and finally ANDs that result with e. The final result is saved in the variable n.

CAUTION: The bitwise AND (&) and OR (|) operators bear a shocking similarity to their logical counterparts && and ||. This can lead to painfully undetectable errors. The same care that is exercised with = and == should also be used with these operators.

The unary bitwise NOT operator (~) changes each 0 bit in its operand to a 1 bit, and each 1 bit in its operand to a 0 bit. The bitwise NOT of x will have the value 0xFFFFEDCB: x 0000 0000 0000 0000 0001 0010 0011 0100 ~x 1111 1111 1111 1111 1110 1101 1100 1011 While &, |, ^, and ~ operate on bits in place, the shift operators <<, >>, and >>> are used to move bits around. The left shift operator (<<) shifts a set of bits to the left by a specified number of positions, while both >> and >>> move that set of bits to the right in two potentially different ways. For example, let us evaluate these three expressions: xleft = x << 5; ysright = y >> 3; yusright = y >>> 3; The first of these shifts each bit in x to the left by five positions. Zero bits are tacked on at the right,

while the bits that are shifted out at the left are lost when they exceed the overall 32-bit length. So the value of xleft must be 0x00024680. The signed right shift operator acts in almost the same way. Each bit of y is shifted to the right by three positions. Bits on the right edge of y are lost as they are shifted out. However, rather than shifting in zeroes at the left side of y, the most significant bit of y, which happens to be 1 in this case, is shifted in. The resulting value of ysright is 0xF0001579. This might seem counterintuitive, but it makes good mathematical sense, since it preserves the sign of the operand. If y is negative (most significant bit set, as in our example) then any signed right shifted version of y will also be negative. Similarly, if y had been positive (most significant bit equal to 0), then any right-shifted version of y would have been positive. The unsigned right shift operator (>>>) does not preserve the sign of its operand; it always shifts 0 bits in at the left edge. The value of yusright is therefore 0x10001579. The shift processes used to compute xleft, ysright, and yusright are shown in Figure 2.2. Figure 2.2 JScript's shift operators move bits to the right or left, and are equivalent to multiplication or division by a power of two. Since all the bitwise operators act at the bit level, chaos can result if they are applied to a variable that is not an integer. Floating-point numbers are particularly sensitive, since an arbitrary bit pattern need not correspond to a valid floating-point number.

CAUTION: Never perform bitwise operations on floating-point numbers. Your code will be unportable, and floating-point exceptions may result.

Assignment and Aggregate Operators. Our tour of JScript operators concludes with the assignment operator and its aggregates. You have already seen many examples of that most fundamental of all operators, the assignment operator (=). You are well aware that it is used to assign the result of an expression or value on the right side of the = sign to the variable or lvalue on the left side of the = sign. In JScript, as in C, C++, and Java, you can also combine the assignment operator with any of the binary computational and logical operators. The expression: Left OP= Right ; is just a shorthand for the expression: Left = Left OP Right ; where OP is any of the operators +, -, /, *, %, &, |, ^, <<, >>, or >>>. So to add 7 to x, multiply y by 19.5, OR z with 0xAA7700, and perform an unsigned right shift of 10 bits on w, you can write:

x += 7; y *= 19.5; z |= 0xAA7700; w >>>= 10; These compact expressions replace the wordier versions x = x + 7; y = y * 19.5, and so forth. Order of Evaluation. In elementary school math, you were probably confronted with questions such as, "What is the value of 3 + 4 * 5? Is it 23 or is it 35?" This was your first exposure to the concept of order of evaluation, or operator precedence. You probably remember that multiplication has a higher precedence than addition, so that the correct answer is 23. The same issue arises in almost every programming language with the concept of operators--which comes first? There are two approaches to this issue. The first involves learning, or attempting to learn, the operator precedence table. The more operators there are, the more rules there must be in this table. The second approach is to simply ignore the issue completely and explicitly group your expressions using parentheses. Never write 3 + 4 * 5. Always write 3 + ( 4 * 5 ) or even ( 3 + 4 ) * 5, if that is what you want. This recommendation is very much like several others in this chapter. It trades the effort (and perhaps some readability) of using the explicit parenthesized form against the promise that the order of evaluation will always be exactly as you wrote it. Incorrect order of evaluation is almost certainly the second most common source of programming error in JScript (confusing = and == is the first). For the daring, Figure 2.3 shows the operator precedence table for JScript. For everyone else, the following tip contains the recommended rule of thumb. Figure 2.3 Use the operator precedence table to determine the order of evaluation.

TIP: Use parentheses to explicitly specify the order of evaluation in expressions containing more than one operator.

There is one case in which no amount of parentheses will help. When using the increment (++) and decrement (--) unary operators, you must simply know that preincrements and predecrements always happen before anything else.

Comments in JScript Code


All professional code should have comments that clearly indicate the purpose and logic behind each major section of the code. JScript offers two comment styles--the original comment style from C and the single line comment style from C++ and Java. C style comments are typically used to document major functions or code blocks. Because a C comment may extend over multiple lines, it is ideal for detailed discussions of important parts of the

code. A C comment begins with /* and ends with */. Our aesthetically pleasing function beaupage() might begin with a thorough description of just what makes it so beautiful, as follows: /* The function beaupage() draws a stunningly beautiful Web page by performing the following nineteen steps. ... list of the 19 steps */ By contrast, C++ style comments are most suitable for short, pithy descriptions which will fit on a single line. A C++ style comment begins with // and ends at the end of the current line. Critical variables, for example, might merit a C++ style comment indicating how they will be used, as follows: var done = false; // set to true when we are all done Both comment styles may be mixed freely in the same JScript program. However, such comments should never be nested, as this can lead to confusion. Also, the temptation to use HTML style comments (<!-- and -->) should be strongly resisted, for reasons which will become clear in the next chapter. See the section, "The <SCRIPT> Tag," of Chapter 3, "Events and JScript," for more information on the relationship between HTML comments and JScript.

TROUBLESHOOTING: I have just written my first JScript program. Everything looks just fine, but the code does nothing. What is wrong? Here is the code: /* My first JScript program *? ...many lines of code not shown /* End of my first JScript program */ Your comments are well thought out and informative. Unfortunately, your very first comment begins with /* but does not end with */. You have inadvertently typed *? instead of */, so that the comment does not end until very far down in your program. When you use C-style comments, always make sure that they match.

Control Structures
At this point, you have had just enough of the JScript language to declare variables, perform assignments, and do various types of arithmetic, string, and logical calculations. You are not yet able

to write any meaningful code, because you do not have any higher-level constructions. In this section, we will consider various methods of controlling the way in which statements are executed. The next section will expose the highest level of JScript--its functions and objects. There are three types of control structure in JScript, as follows:
q q q

while for if

These three control structures are very similar. Each is introduced by a keyword (while, for, and if, respectively) and each manipulates a block of JScript statements. A block is introduced by a left brace ({) and terminated with a right brace (}). There can be as many JScript statements between { and } as you want, or as few. A block of code can even be empty, with nothing between the braces. In many ways, a block of statements is like a single gigantic statement. In particular, block-structured constructs are often all or nothing--either the entire contents of the block are executed, or none of it is. Since blocks behave like single statements, it is also possible to put blocks inside other blocks, in a nested fashion. As you will see, each of the three control structures has its own specific format and its own special uses, although it is often possible to achieve the same results using any of the three types, with varying degrees of elegance.

The if Statement
The if statement is used to conditionally execute a single block of code. It has two forms, the simple if statement and the if...else statement. The simple if statement consists of a conditional expression, known as the if test, and a block of code which is executed if that expression evaluates to a Boolean true. An example of an if statement follows: if ( condstmt ) { zero or more statements } The block of code within the braces is often called the if block. The conditional statement condstmt can be any expression that yields a logical value. Note that numerical expressions may also be used; 0 is construed as false, and all other values are taken to be true. As stated earlier, an if statement should be considered a single statement. Code blocks are not traditionally terminated with a semicolon, although there is no harm in doing so. Listing 2.1 shows an example of a simple if statement.

Listing 2.1 The if Control Structure


if ( ( x < 10 ) && ( -10 < x ) ) { // if test

y = ( x * x * x ); // 1: cube of x ystr = "The cube of " + x + " is " + y; // 2: informative string } In this example, the value of x is tested to see whether it is less than 10 and also greater than -10. If the result of this test is true, then the variable y is set equal to the expression x * x * x, known mathematically as the cube of x, in the statement 1 (labeled 1:). The variable ystr is then set to a string that expresses this cubic relationship between x and y, in statement 2. If x fails either of the two tests in the if test, neither of the two statements in the if block is executed. It is easy to see even in this simple example that it is often desirable to have a contingency plan in case the if test is false. This leads to the second form of the if statement, the if...else control structure. In this form, one block of code is executed if the if test passes, and a second block is executed if it fails. The format of this type of if statement is as follows: if ( condstmt ) { ifblock of statements } else { elseblock of statements }

NOTE: In the current version of JScript, the placement of the braces is not important. The opening brace ({) may be on the same line as the if keyword or on the line immediately following it. Earlier versions, such as the JavaScript release bundled with Netscape Navigator 2.0, enforced much stricter rules on where { and } could be put.

In this form of the if statement, the if block is still executed if condstmt is true. However, in this case, the block of code following the else is executed if condstmt is false. Listing 2.2 shows an enhanced version of the code from Listing 2.1 using the if...else form.

Listing 2.2 The if...else Control Structure


if ( ( x < 10 ) && ( -10 < x ) ) { // if test y = ( x * x * x ); // 1: cube of x ystr = "The cube of " + x + " is " + y; // 2: informative string } else { // false case y = null; // 3: be paranoid; give y a value ystr = "Cannot compute the cube of " + x; // 4: explain the failure } In this example, statements 1 and 2 are still executed if x meets both tests in the if test. If either test

fails, statements 3 and 4 in the else block are executed instead. Statement 3 is another example of defensive programming. The variable y is given a value, albeit a meaningless value. This is done so that if y is used later, it will be guaranteed to have some value (even if we forgot to initialize it) regardless of whether the code flowed through the true part of the if (the if block) or the false part of the if (the else block). Observe that ystr also gets a value no matter which of the two blocks is used. In the true case, it has the informative string documenting the cube of x; in the false case, it has a string indicating that the cube of x could not be computed. Because ystr will presumably be displayed to the user at some point, it is worthwhile to provide an error message. This is an example of parallel code design. Each conditional path modifies the same set of variables. For a simple case, such as Listing 2.2, it is easy to ensure that this happens. There are only two variables, y and ystr, and we can see exactly where they are set in every case. For more complicated, nested conditional expressions, it can become almost impossible to observe every variable in every case. Parallel code design is a good goal to strive for nonetheless.

The while Statement


The while statement is used to execute a block of code while a certain condition is true. The format of the while statement is as follows: while ( condstmt ) { zero of more statements } The condition clause condstmt is evaluated as a logical expression. If it is true, the block of statements between the braces is executed. The flow of control then loops back to the top of the while statement, and condstmt is evaluated again. This process continues until the condstmt becomes false, or until some statement within the block forces it to terminate. Each pass through the block of code is called an iteration. Figure 2.4 illustrates the basic structure of a while statement. Figure 2.4 JScript's while control structure executes a block of statements conditionally. The first fundamental difference between a while statement and an if statement is that the while block may be executed many times, while the if or else blocks are executed once at most. You might well wonder how a while statement ever terminates. The code shown in Listing 2.3 illustrates a simple situation in which the while block eventually leads to the condstmt becoming false.

Listing 2.3 A while Loop which Adds a Sequence of Numbers


var x = 1; var xsum = 0; while ( x <= 10 ) { // loop until x is greater than 10

xsum += x; // add x to the running sum xsum x++; // increment x } This code accumulates the sum of all the integers between 1 and 10, inclusive, in a variable called xsum. x starts out as 1, so that xsum initially becomes 1 as well. x is then incremented to 2 by the x+ + statement. That value is then added to xsum, so that it becomes 1 + 2 = 3. This process continues until x finally becomes 11 and the x <= 10 condition is false. xsum at this point has the value 1 + 2 +...+ 9 + 10 = 55. Thus, the loop terminates. Note that it is critically important to initialize xsum to 0. If xsum is not initialized at all, then the statement xsum += x, which is just shorthand for xsum = xsum + x, gives an error. If xsum is initialized to something other than 0, the final result contains that initial value and is not just the sum of the integers from 1 through 10. Listing 2.3 shows one way in which a while loop can terminate. Statements within the block may cause the conditional statement to become false. It could also happen that the conditional statement at the top of the while was never true, so that the statements within the block are not executed even once. If x had started with the value 20 in this example, the while test would have been immediately false, and the statements xsum += x and x++ would have never been executed. In this event, xsum would retain its initial value of 0. Using the break Statement. There is a third way for a while loop to terminate. If the special statement break is encountered inside the while block, the loop is forced to terminate immediately. No further statements are executed, and the condstmt is not retested. Execution continues with the first statement after the end of the while block. Listing 2.4 gives an example of the use of the break statement.

Listing 2.4 A while Loop with an Internal break Statement


var var var var x = 1; xoddsum = 0; xtmp = 0; lastx = 0;

while ( true ) { // 1: loop forever (well, almost) xtmp = xoddsum + x; // 2: compute a trial sum if ( xtmp > 100 ) // 3: if it is too large, then... break; // 4: we are done xoddsum += x; // 5: add x to the running sum xoddsum x += 2; // 6: increment x by 2 } lastx = x; // 7: save the final value of x in the variable lastx The test clause of this while (statement 1) is true, which, you might well suspect, is always true. This means that there is no way for this loop to terminate unless it is forced to do so by a break statement. In statement 2, a temporary sum is formed in the variable xtmp. This sum is

tested against the limit 100 in statement 3; if xtmp exceeds it, then statement 4, the break statement, is executed, and the loop terminates. If the test fails (xtmp is still less than 100), then the real sum is formed in statement 5. (Note that it would have been equivalent, and slightly more efficient, if we had written statement 5 as xoddsum = xtmp.) In statement 6, x is incremented by 2. What does this while loop do? It keeps adding up numbers, odd numbers in fact, until the sum is less than 100. When the next sum would have exceeded 100, the if test succeeds, the break is executed, and the flow of control of the program reaches the first statement after the entire while block, namely statement 7. This statement saves the last value of x in a different variable, lastx. This construction computes the largest sequence of odd numbers that can be added without having the sum exceed 100. You can easily determine for yourself that the value of lastx must be 21, since 1 + 3 + ... + 21 = 100 exactly, while 1 + 3 + ... + 21 + 23 = 123 > 100. The Perils of Infinite Loops. Listing 2.4 not only illustrates the use of break, it also shows two other elements worth noting. First, Listing 2.4 contains a nested conditional: There is an if statement inside the while block. This sort of construct is extremely common, and many levels of nesting are not at all unusual. Second, this example has another very common but somewhat troublesome feature. Since the while test is always true, there is no way for the while to terminate unless the break statement is executed. In the preceding example, it was quite quickly. Suppose, however, that statement 6 had been incorrectly entered as x -= 2. In this case, xoddsum would be getting constantly smaller and xtmp would never exceed 100. This type of error is known as an infinite loop. Listing 2.3 is not immune either, even though it has a conditional test rather than a blanket true. If the final statement of that example had been mistyped as x--, it would never terminate either. Naturally, infinite loops must be vigorously avoided. They will terminate only when some kind of internal error happens (such as an arithmetic overflow when something becomes too large) or as a result of user intervention. Unfortunately, there is no foolproof way to write a while statement (or a for statement, as we shall see shortly) that is guaranteed to be correct. JScript is no different from any other programming language in this respect. However, the following general principles will reduce the opportunity for error:
q q

Avoid while ( true ) whenever possible. Have at least one way of exiting the loop body.

If the while ( true ) construction is used, then the logic that exercises the break statement must be correct. If this logic isn't correct, the loop will never terminate. If you restrict your use of while ( true ), you will have fewer infinite loops. The second suggestion is based on the observation that the more chances there are to exit the loop, the less likely it is that the loop will last forever. Listing 2.5 shows a modified version of Listing 2.4 in which we have moved the test on the sum to the while clause itself, and have also added a very paranoid test on the number of times through the loop (the variable loopcount).

Listing 2.5 An Improved Form of Listing 2.4


var x = 1;

var xoddsum = 0; var lastx = 0; var loopcount = 0; while ( ( xoddsum + x ) < xoddsum += x; // 2: add x x += 2; // 3: increment x if ( ++loopcount > 1000 ) break; // 5: quit } lastx = x; // 6: save the 100 ) { // 1: loop while sum is < 100 to the sum xoddsum by 2 // 4: if we're working too late..

final value of x in lastx

This version satisfies both rules. Of course, the test in statement 4 is completely unnecessary. The code is simple enough that we can reassure ourselves that it is correct and will not go into an infinite loop. Once you are writing slightly more complicated while loops, you will find that there are usually multiple possible error conditions that arise. Every time you test for an error, you should consider using a break statement. You will often see while ( true ) written as while ( 1 ). These are equivalent, since true has the numerical value 1, but the latter form is sloppy. The conditional portion of a while, if, or for statement should always be a true logical expression. Using the continue Statement. There is another special statement that may be used inside while loops: the continue statement. The continue statement is used to force the flow of control back to the top of the while loop. When a continue statement is seen, all statements between it and the end of the while block are skipped, and execution continues at the top of the while. Listing 2.6 shows a simple use for the continue statement.

Listing 2.6 A continue Statement Returns to the Top of a while


var x = 0; var xsum = 0; var loopcount = 0; while ( loopcount++ < 100 ) { // 1: loop 100 times x++; // 2: increment x if ( ( x % 5 ) == 0 ) // 3: if x is divisible by 5 continue; // 4: skip it xsum += x; // 5: otherwise, add x to xsum } This example adds up every number between 1 and 100 that is not divisible by 5. The numbers that are divisible by 5 are skipped by virtue of statements 3 and 4. Statement 3 computes the remainder when x is divided by 5. If that remainder is 0, then x must be evenly divisible by 5. In that case, the conditional in statement 3 is true, and statement 4 is executed. The continue statement causes execution to continue back to the top of the loop at statement 1. This means that statement 5 is not

executed, so the sum always misses those values of x which are divisible by 5, and only those values. Many programmers would write line 3 as if ( ! ( x%5 ) ). While this style is very common, it is also confusing and a potential source of error. One problem with this form is that it confuses JScript types by using the numerical value x%5 as if it were a logical value. This form also hides the explicit test for zero of Listing 2.6. While this ! form is more compact, it is also more error-prone, and should be avoided. One striking difference between this listing and previous ones is that x is initialized to 0, not 1, and x is incremented at the top of the loop, not at the bottom. If the x++ were at the bottom, what would happen? The values 1, 2, 3, and 4 would all be gleefully added into xsum. When x reached 5, however, statement 3 would be true, the continue in statement 4 would be executed, and both xsum += x and x++ would be skipped. x would stay equal to 5 forever! Since the x++ statement is critical to the correct functioning of the loop, it must occur before the continue. If it occurs after the continue, it will be skipped.

CAUTION: Any statement that must be executed on every pass through a loop must be placed before any continue statements.

The for Statement


The for statement is the most powerful and complex of the three flow control constructions in JScript. The primary purpose of the for statement is to iterate over a block of statements for some particular range of values. The for statement has the following format: for ( initstmt; condstmt; updstmt ) { forblock } The for clause, as shown, has three parts, separated by two mandatory semicolons. The initstmt is typically used to initialize a variable, although any valid statement may be used in this position. The initstmt is always executed exactly once, when the for statement is first encountered. The condstmt is a conditional test, and serves exactly the same function as in the while statement. It is tested at the top of each loop. The for statement terminates when this condition evaluates to false. The updstmt is executed at the bottom of each loop, as if it were placed immediately after the last statement in the for block. It is typically used to update the variable that is initialized by the initstmt. Listing 2.7 shows a simple example of a for statement. In fact, the code in this listing accomplishes exactly the same task as the code in Listing 2.3. Note that this code does not bother to initialize x when it is declared. This is because the initstmt part of the for loop sets it equal to 1

immediately.

Listing 2.7 Adding Up a Sequence of Numbers Using for


var xsum = 0; var x; for ( x = 1; x <= 10; x++ ) { // 1: loop while x is <= 10 xsum += x; // 2: add x to xsum } In many ways, the for statement is very much like a fancy version of the while statement. Many of the observations that were made for while also hold true for the for statement. In particular, it is possible to use the break and continue statements within a for loop. One of the advantages of a for loop is that its update statement is executed on every pass through the loop, even those passes that are cut short by a continue. The continue skips every statement in the block, but it does not cause the update statement to be skipped. The for statement may also be used unwisely, just like the while statement. If the condstmt portion of the for clause is omitted, it is as if a true conditional had been used, so that something within the for block must force looping to terminate. You will occasionally see the construction for(;;), which is identical in meaning to while ( true ). The two semicolons are mandatory. The for statement also has some unique features that are not shared by while. The first is that variables may actually be declared and initialized within the initstmt portion. In Listing 2.7, we could have dispensed with the external declaration of x and put var x = 1; as the initialization portion of the for loop. This is often very convenient, since the loop variable (x in this case) is often used only within the loop itself, making an external declaration pointless.

NOTE: If a variable is used only inside a block of statements, it should be declared at the top of that block. This clarifies your code, since it shows which sections of code use which variables (known as variable scope).

A second useful feature of the for statement is that both the initialization portion and the update portion of the for clause may contain multiple statements separated by the comma operator (,). Listing 2.8 shows another version of the code in Listing 2.6, rewritten so that both x and lcnt become loop variables.

Listing 2.8 A for Loop with Multiple Initialization and Update Statements
var xsum = 0;

for ( var x = 1, lcnt = 0; lcnt < 100; x++, lcnt++ ) { if ( ( x % 5 ) == 0 ) // if x is divisible by 5 continue; // skip it xsum += x; // otherwise, add x to xsum } This usage underlines the fact that both x and lcnt are used only within the body of the for loop. It is also much more compact than its counterpart in Listing 2.6. In this example, we need not worry about the logical effect of the continue; we know that both x++ and lcnt++ will always be executed. This is also the most common and useful way to use the comma operator. Finally, there is another form of the for statement that is used exclusively with objects and arrays in JScript: the for...in statement. We will see how this is used in Chapter 4, "JScript Objects." Figure 2.5 shows the basic structure of the for, while, and if statements, and the use of the break and continue statements within them. See the section, "Objects, Methods, and Properties in JScript," of Chapter 4, "JScript Objects," for a description of the for...in statement. Figure 2.5 Control statements determine the flow of execution in JScript.

CAUTION: The control statements if, for, and while are examples of keywords. Keywords are words which have a special meaning to JScript itself. Keywords may never be used as variable names, so the statement var if = 0; is extremely illegal.

Functions and Objects


The basic statements, expressions, and operators that were discussed at the beginning of this chapter are what computer scientists usually call primitives. Primitives are the building blocks from which more complex elements of a program are constructed. The for, while, and if control structures represent the next higher level of organization in JScript. Each of these control structures deals with blocks of code whose execution is controlled by the various conditional tests and other clauses. The for, while, and if statements are all block-structured. Functions and objects represent the highest level of organization within the JScript language. We will spend many chapters learning how to make effective use of these concepts. The purpose of this section is to introduce them and describe their basic features.

Functions

A function is a block of code that has a name. Whenever that name is used, the function is called, which means that the code within that function is executed. Functions may also be called with values, known as parameters, which may be used inside the body of the function. Functions serve two purposes. A function is an organizational tool, in the sense that it permits you to perform the same operation without simply copying the same code. The second purpose of JScript functions is to link actions on a Web page with JScript code. Mouse clicks, button presses, text selections, and other user actions can call JScript functions by including suitable tags in the HTML source for the page. Event-handler functions are explored in Chapter 3, "Events and JScript," particularly in the "Events and HTML Tags" section. The syntax for a function statement in JScript is as follows: function Name ( listofparams ) { body } The function's Name is given immediately after the function keyword. All function names should be unique, and also should not conflict with any of the statement names which JScript itself uses. You cannot have a function named while, for example, and you should not have two functions both named UserHelp. The listofparams is a comma-separated list of the values that are passed into the function. These are referred to as the function's parameters, or arguments. This list may be empty, indicating that the function does not use any arguments (often called a void function). The function's body is the set of statements that make up the function. Listing 2.9 shows a function that adds up all the integers, starting at 1 and ending at a value given as the sole argument.

Listing 2.9 A Summation function


function summation ( endval ) { var thesum = 0; // this variable will hold the sum for ( var iter = 1; iter <= endval; iter++ ) { thesum += iter; // add the integer into the sum } // end of the for loop return( thesum ); // return the sum } This function does the same task that came up in the discussions of the while and for statements earlier in this chapter. Now that it has been written as a function, this code never needs to be repeated again. Anytime you want to form the sum 1 + 2 + ... + N, you can simply call the function, as summation(N), and it will perform the task. Notice that the endval parameter is used as the

argument to the function. When the function is called, as summation(14) for example, the actual value 14 is used for endval within the function. The function then executes the for statement, with iter <= 14 as its termination condition, adding in each successive value into the variable thesum. When the for loop is done, the function executes the return statement. This causes the function to give the value inside the return statement back to the caller. This means that if we write: var sum14 sum14 = summation(14); the variable sum14 is set to the value returned by the summation function when endval is given the value 14, namely 105. Functions can return any type of value, and are not restricted to returning integers. There are several things to notice about this example. First of all, the variables thesum and iter, which are declared within the body of this function, are local variables. This means that they are known only within the body of this function, and are therefore completely unknown outside it. It is quite possible, even likely, that there are many functions all of which have a local variable named iter. All these various iters are unrelated. Changing the value of one of these iters would not affect any of the others. This is why the return statement is necessary; it is the only way to communicate the work of the function back to the caller. This same restriction applies to the parameter endval as well. The arguments to a function may not be changed within that function. We could well have written endval = 15 just before the return statement in Listing 2.9. This statement would do nothing; It certainly would not change the caller's 14 into a 15. It might seem that every function would always have a return statement. This is not the case, however, because it is possible for a function to have side effects without actually returning a value. This happens by referencing external objects, which are our next topic.

Objects
Functions are used to provide a uniform method for organizing code. Objects serve the same purpose for data. Up to this point, the only data items we have seen are simple variables declared with var. Each of these typeless quantities can hold only a single value of some sort at a time. Objects provide the ability to hold multiple values, so that a group of related data elements can be associated with one another. What JScript calls an object is called a data structure (or class) in many other languages. As with JScript functions, there are two aspects to JScript objects: creating them and using them. For the moment, we will defer the question of how to create objects and concentrate on how they are used. We will also see that a JScript-capable browser will provide a number of its own, built-in objects. A JScript object is made up of a set of component parts, which are called its properties, or members.

Suppose you have an object named appt which you are using to organize your appointments. The appointment object might have properties that specify the date and time of the appointment, as well as the name of the person with whom the appointment will take place. It might also have a general description field to remind you of the purpose of this meeting. Thus, you can imagine that the appt object will have the following properties:
q q q q q

day month time who why

Each of the properties of the appt object is referenced using the dot operator (.). Thus, appt. month refers to the month property and appt.why gives us the reason for the appointment. These references may appear on both the right and left sides of an expression; we may get their values and also set them. Listing 2.10 shows a code fragment that tests the value of appt and displays a message about a current appointment.

Listing 2.10 Using the appt Object


if ( appt.day == Today ) { document.write(`<BR>You have an appointment today<BR>'); document.write(`See ` + appt.who + ` at ` + appt.time + `<BR>'); document.write(appt.why + `<BR>'); } This example assumes that the variable Today has somehow been initialized with today's date, so that the equality test with appt.day is true only for today's appointments. If the test does succeed, then the three statements in the if block are executed. Each of these references document.write. The document object is a built-in object of the browser. This object has a member known as write, which is actually a function. Functional members of JScript objects are known as methods. This particular method takes a string and displays it on the current Web page. Each of the three strings that are passed to document.write are constructed using + as a string concatenation operator. Each of them references one or more properties of the appt object in order to provide meaningful messages to the user. Each also includes <BR>, the HTML construction for a line break. This ability directly to issue HTML directives is one of the most powerful aspects of JScript, as it allows the programmer dynamically to modify the contents of Web pages using JScript functions and objects. Once you learn more about the Date object, in "The Date Object" section of Chapter 5, you will be able to construct a much more satisfying version of this example. Even at this stage, however, the advantage of object-based programming should be apparent. Rather than carrying about many variables, you can use objects instead. Each object can contain all the variables of interest to a particular idea. It can also contain method functions that perform related work. Objects can even

contain other objects, so that you can organize your data in a hierarchical structure. Subsequent chapters explore these ideas in much greater detail.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Chapter 16 Creative User Interaction


q

Creative User Interaction r Creating Dynamic Output r Generating Random Numbers r A Random Phrase Generator s Random Words s The Phrasemaker s Colors, Fonts, and All s Adding and Sorting Words r An Online Bookstore s Parsing Free-Form User Input s Building an Index s Defining Book and Catalog Objects s The Bookstore s Improved Indexing and Searching

Creative User Interaction


q q q q q

Create dynamic output Generate random numbers Sort an array Parse free-form user input Create an indexed database

JScript offers tremendous flexibility in interacting with the user. You can create entire documents onthe-fly. You can dynamically customize both the content of a document and its appearance according to user criteria and other factors. User input also benefits from this flexibility: Prompts can be dynamically generated, and even free-form input can be processed. In this chapter, you develop techniques for performing all these tasks. This chapter builds on several of the objects you created in Chapter 15, "Visual Effects," and some of the techniques you developed there, so you might want to review that chapter before you begin, or refer to it as you go along.

Creating Dynamic Output

JScript provides two methods of updating the screen with dynamic content: You can use the document.write() function, or you can write the entire contents of a frame to the screen using the javascript: protocol. As in Chapter 15, you use the latter approach here because it is better suited to the examples in this chapter. The skeleton frameset shown in Listing 16.1 is essentially the same as that used in Chapter 15.

Listing 16.1 The Skeleton Frameset


<html> <head> <title>Creative User Interaction</title> <script language="JavaScript"> <!-- begin script var emptyFrame = `<html></html>`; function headFrame () { return `<html><body bgcolor="#FFFFFF" text="#000000">` + `<h1 align="center">Creative User Interaction</h1>` + `</body></html>`; } function initialize () { self.head.location = "javascript:parent.headFrame()"; } // end script --> </script> <frameset rows="52,*" onLoad="initialize()"> <frame name="head" src="javascript:parent.emptyFrame" marginwidth=1 marginheight=1 scrolling="no" noresize> <frame name="body" src="javascript:parent.emptyFrame"> </frameset> <noframes> <h2 align="center">JScript or JavaScript enabled browser required</h2> </noframes> </html> In this Listing, you start by initializing the frames to point to the emptyFrame variable in the FRAME SRC= tag and then set the true location from the initialize() function, which is the onLoad handler for the frameset. As noted in the preceding chapter, this gets around an alignment bug that appears when loading a frame directly using the javascript: protocol. You can specify either a variable or a function name on the right side of the colon in a javascript: URL. Normally, you use a variable to return an unchanging, or static, value, whereas you use a function to return dynamic content. If a variable name refers to an object, however, and that object has a toString() method defined, the function associated with the

toString() method is called when the object is referenced in a javascript: URL, in which case dynamic content may be returned. You see an example of this behavior in the section entitled "A Random Phrase Generator." You have defined headFrame() as a function, although it currently returns a static value. You can jazz it up with a little bit of dynamism, as shown in Listing 16.2.

Listing 16.2 Returning Dynamic Content


function headFrame () { var now = new Date(); var body; if (now.getHours() >= 6 && now.getHours() < 18) body = `<body bgcolor="#FFFFFF" text="#000000">`; else body = `<body bgcolor="#000000" text="#FFFFFF">; return `<html>` + body + `<h1 align="center">Creative User Interaction</h1>` + `</body></html>`; } Now, when headFrame() is loaded between 6:00 A.M. and 6:00 P.M., it comes up in "daylight" mode, with a white background. From 6:00 P.M. until 6:00 A.M., the function displays its nocturnal mode. But why stop here? You can give the user an appropriate greeting as well, as shown in Listing 16.3.

Listing 16.3 Returning a Timely Greeting


function headFrame () { var now = new Date(); var hour = now.getHours(); var body; var greeting; if (hour >= 6 && hour < 18) body = `<body bgcolor="#FFFFFF" text="#000000">`; else body = `<body bgcolor="#000000" text="#FFFFFF">; if (hour < 6) greeting = "Up late, or up early?"; else if (hour < 12) greeting = "Good morning!"; else if (hour < 18) greeting = "Good afternoon!"; else

greeting = "Good evening!"; return `<html>` + body + `<h1 align="center">Creative User Interaction</h1>` + `<h3 align="center">` + greeting + `</h3>` + `</body></html>`; } One result of this Listing is shown in Figure 16.1. Figure 16.1 The current time is used to generate an appropriate greeting.

Generating Random Numbers


In the preceding example, you used the time of day to determine which colors and messages to use in generating a dynamic header frame. You can take this example even further; for instance, you might define a different message for every hour of the day, or even for every minute of the hour. You can use this technique to give your pages many different looks. For many applications in which a degree of apparent randomness is desirable, using the Date object alone yields acceptable results. When you need a series of "random" numbers, one after another, however, the Date object isn't of much help. Chances are, whatever calculations you're performing or effects you're creating will be finished before the Date object advances to a new value. A Random Number Generator (RNG) comes into play here. In truth, no such thing as a software-generated "random" number really exists. Software is hopelessly logical--given a particular set of input values, a function performs a predefined set of steps in a predictable order, yielding predictable results. (Even a buggy function yields predictable, if undesirable, results.) Even the best algorithms, such as the one presented in the next paragraph, don't generate truly random numbers. Instead, they generate very long sequences of numbers that simulate random behavior. However, eventually the sequences repeat. The numbers generated are therefore properly known as pseudo-random numbers. The RNG shown in Listing 16.4 is an implementation of the Park-Miller algorithm. (See "Random Number Generators: Good Ones Are Hard to Find," by Stephen K. Park and Keith W. Miller, Communications of the ACM, 31(10):1192--1201, 1988.) The JScript version was written by David N. Smith of IBM's T.J. Watson Research Center. Mr. Smith notes that his version has not been subjected to the rigorous testing required of a mission-critical RNG.

Listing 16.4 The RandomNumberGenerator Object


function NextRandomNumber() {

var hi = this.seed / this.Q; var lo = this.seed % this.Q; var test = this.A * lo - this.R * hi; if (test > 0) this.seed = test; else this.seed = test + this.M; return (this.seed * this.oneOverM); } function RandomNumberGenerator() { var d = new Date(); this.seed = 2345678901 + (d.getSeconds() * 0xFFFFFF) + (d.getMinutes() * 0xFFFF); this.A = 48271; this.M = 2147483647; this.Q = this.M / this.A; this.R = this.M % this.A; this.oneOverM = 1.0 / this.M; this.next = NextRandomNumber; return this; } In the preceding Listing, the RandomNumberGenerator() constructor uses the system time, in minutes and seconds, to "seed" itself, that is, to create the initial values from which it will generate a sequence of numbers. If you are familiar with random number generators, you might have reason to use some other value for the seed. Otherwise, you should probably not change it. This RNG is implemented as an object. To use it, you create an instance of the object and then invoke its next() method to return a number. Each call to the next() method returns a new random number, as in the following: var rand = new RandomNumberGenerator(); // Display five random numbers for (var i = 0; i < 8; i++) document.write ("The number is: " + rand.next() + "<br>"); A simple example page which displays eight random numbers when a button is clicked is given in the CD-ROM file rng.htm. Like many random number generators, this RNG returns a fraction between 0 and 1; for example, .2755983265971, or something similar. To convert this number to an integer between 0 and n, you must multiply n times the random number and then round the result. Here's an example that returns a random number between 0 and 255: function random255 () { return Math.round(255 * rand.next());

} This example works fine if you need only random integers between 0 and 255. But you can rewrite it to return a number between 0 and any integer, as follows: function random (n) { return Math.round(n * rand.next()); } By now, you might be starting to wonder, why all the fuss about random numbers? What use are they, anyway? Well, they have many serious and important uses, in simulations, in software testing and verification, and so on. They also happen to be great for creating games and other fun things, as you see in the next section. NOTE: You might have noticed that JScript's Math object includes a built-in random () method. The version presented here should work as well as, if not better than, the built-in implementations, and will work uniformly on all platforms.

A Random Phrase Generator


According to one popular theory, if you put enough monkeys in a room full of typewriters, eventually, by hit and miss, they will bang out the complete works of Shakespeare. Although we suspect it would take several generations of monkeys just to tap out a decent sonnet, try a similar, but less ambitious, experiment here, using the random number generator in place of monkeys. The goal here is to generate some simple phrases by randomly combining words from lists of verbs, articles, adjectives, and nouns. In this exercise, you can cheat a little bit by imposing a structure on the phrases. Your formula is as follows: verb + article (or possessive pronoun) + adjective + noun. For example, Have a nice day.

Random Words
Start creating the random phrase generator by defining an object to contain a list of words, as shown in Listing 16.5.

Listing 16.5 The Word Object Constructor

function Word () { var argv = Word.arguments; var argc = argv.length; this.list = new Object(); for (var i = 0; i < argc; i++) this.list[i] = argv[i]; this.count = argc; this.toString = WordString; return this; } function WordString () { var i = Math.round((this.count - 1) * rand.next()); return this.list[i]; } The Word() constructor is designed to accept a variable number of parameters, or arguments. Every JScript function has a built-in property called arguments. The arguments property is an array containing all the arguments passed to the function, indexed beginning at 0. The arguments property also has a length property, which is the number of arguments passed to the function. You assign them to variables argv and argc, primarily because variables by those names play a similar role in C programs. The Word() constructor takes the words passed in the argument list and puts them in an internal array called list. To keep the numbering scheme simple, you can make list a separate object rather than make each word a property of the Word object itself. The toString() method WordString() does the monkey's job of returning random words. As you learned in Chapter 15, JScript automatically calls an object's toString() method any time the object is used in a context requiring a string. WordString() uses the random number object rand to generate an integer between 0 and the number of words in the list minus one. (If you have a list containing five words, the generated integer is 0-4.) This integer is then used as the index into the list array. To start, use the Word() constructor to create a list of nouns: var noun = new Word ("dog", "cat", "shoe", "doorknob", "umbrella"); Now, each time you refer to the noun object in a context requiring a string (thus invisibly calling its toString() method), you get a random selection from the list. For instance, consider this code snippet: for (var i = 0; i < 5; i++) document.write ("Have a " + noun + "<br>"); It returns a list of offerings that might look something like the following:

Have Have Have Have Have

a a a a a

shoe umbrella cat dog doorknob

Sample output is shown in Figure 16.2. The source code which generated this output will be found in the CD-ROM file rword.htm. Figure 16.2 The RNG object is used to construct simple random sentences. As you can see, just because you reference the noun object five times does not mean that each of the five words will be listed. Randomness means that you might get just one of the words repeated five times. Or you might get all five perfectly alphabetized. Over time, these instances will roughly average out, but you have no way of knowing what you'll get in any given sample. Now go ahead and define the rest of the word types, and take a crack at some random phrases, as follows: var verb = new Word ("have", "get", "eat", "pet", "feed"); var article = new Word ("a", "the", "my", "your"); var adjective = new Word ("nice", "pretty", "smelly", "hairy", "yellow"); for (var i = 0; i < 5; i++) document.write (verb + " " + article + " " + adjective + " " + noun + "<br>"); To add variety to the phrases, you can include a couple of possessive pronouns in the article object, as shown in the preceding code. Here's one possible set of generated phrases: get your nice shoe pet a smelly umbrella pet your hairy shoe feed my yellow dog eat the hairy doorknob How many different phrases can you generate? Right now, you can calculate the number of phrases as the number of verbs (5) times the number of articles (4) times the number of adjectives (5) times the number of nouns (5), or a total of 500 phrases. But you're about to increase that number more than tenfold.

The Phrasemaker

Having a function that returns a complete phrase would be convenient. While you're at it, you can add the ability to vary the structure of the phrases and include some special handling for plural nouns, as well as adjectives or nouns that begin with vowels. Listing 16.6 gets you started.

Listing 16.6 The phrase() Function


function isVowel (ch) { if (ch == `a' || ch == `e' || ch == `i' || ch == `o' || ch == `u') return true; return false; } function phrase (adjs) { var plural = (rand.next() >= .5); // Sets plural to true or false var vb = verb.toString(); var first = vb.charAt(0); var vb = first.toUpperCase() + vb.substring(1,vb.length); var art = article.toString(); var adj = new Object(); for (var i = 0; i < adjs; i++) adj[i] = adjective.toString(); var nn = (plural) ? pluralNoun.toString() : singularNoun.toString(); if (plural && art == "a") art = "some"; if (art == "a") { if (adjs > 0) first = adj[0].charAt(0); else first = nn.charAt(0); if (isVowel(first)) art = "an"; } var ph = vb + " " + art + " "; for (i = 0; i < adjs; i++) ph += adj[i] + " "; ph += nn; return ph; } var singularNoun = new Word ("dog", "cat", "shoe", "doorknob", "umbrella"); var pluralNoun = new Word ("dogs", "cats", "shoes", "doorknobs", "umbrellas"); In this Listing, the phrase() function takes as a parameter the number of adjectives to be included

in the phrase, and it returns a complete phrase with the first letter capitalized. The function uses the random number generator to decide whether the noun will be singular or plural. The article "a" is also given special handling: If the noun is plural, "a" is changed to "some"; if it precedes a word beginning with a vowel, it is changed to "an." Notice that you call the toString() methods for the Word objects directly here. Because of the special handling you're doing, you aren't using them in a string context, so toString() isn't called automatically by JScript. In this Listing, you also define new Word objects for singular and plural nouns. Although plural nouns could be created from the singular nouns used here by appending "s" to the end of each, many irregular nouns cannot be transformed easily. Note that the singularNoun and pluralNoun objects could contain completely different words, and even different numbers of words. Here's an example of using the phrase() function: document.write (phrase(0) + "<br>"); document.write (phrase(1) + "<br>"); document.write (phrase(2) + "<br>"); The source code which implements this simple example will be found in the CD-ROM file rphrase. htm. The phrases generated might look something like this: Buy an umbrella Eat your smelly cats Have the nice yellow doorknob

Colors, Fonts, and All


Up to this point, you've been testing the phrase generator using simple document.write() calls. Put it in a frameset now, with all the trimmings. Because you're experimenting with random numbers, you can use them in the display process as well, to generate random color schemes and fonts for the phrases. Briefly review a few of the objects you created in Chapter 15 for putting text on the screen. These objects simplify the process of creating random colors and fonts for the phrase generator. Listing 16.7 shows the Color object.

Listing 16.7 The Color Object Constructor


var hexchars = `0123456789ABCDEF'; function fromHex (str) { var high = str.charAt(0); var low = str.charAt(1);

return (16 * hexchars.indexOf(high)) + hexchars.indexOf(low); } function toHex (num) { return hexchars.charAt(num >> 4) + hexchars.charAt(num & 0xF); } function Color (str) { this.red = fromHex(str.substring(0,2)); this.green = fromHex(str.substring(2,4)); this.blue = fromHex(str.substring(4,6)); this.toString = ColorString; return this; } function ColorString () { return toHex(this.red) + toHex(this.green) + toHex(this.blue); } The Color object holds a color. It stores the red, green, and blue components as numbers (0-255). The Color() constructor accepts a hexadecimal triplet of the form RRGGBB, whereas the toString() method, ColorString(), converts the internal values back to this format. Listing 16.8 shows the BodyColor object.

Listing 16.8 The BodyColor Object Constructor


function BodyColor (bgColor,fgColor,linkColor,vlinkColor, alinkColor) { this.bgColor = bgColor; this.fgColor = fgColor; this.linkColor = linkColor; this.vlinkColor = vlinkColor; this.alinkColor = alinkColor; this.toString = BodyColorString; return this; } function BodyColorString () { return `<body' + ((this.bgColor == null) ? `' : ` bgcolor="#' + this.bgColor + `"`) + ((this.fgColor == null) ? `' : ` text="#' + this.fgColor + `"`) + ((this.linkColor == null) ? `' : ` link="#' + this.linkColor + `"`) + ((this.vlinkColor == null) ? `' : ` vlink="#' + this.vlinkColor + `"`) + ((this.alinkColor == null) ? `' : ` alink="#' + this.alinkColor + `"`) +

`>'; } The BodyColor object contains one or more Color objects corresponding to the HTML color attributes that can be specified in a body tag. Its toString() method returns a formatted body tag, including any specified colors. Listing 16.9 shows the Text constructor.

Listing 16.9 The Text Object Constructor


function Text (text, size, format, color) { this.text = text; this.length = text.length; this.size = size; this.format = format; this.color = color; this.toString = TextString; this.substring = TextString; return this; } function TextString (start, end) { with (this) { if (TextString.arguments.length < 2 || start >= length) start = 0; if (TextString.arguments.length < 2 || end > length) end = length; var str = text.substring(start,end); if (format != null) { if (format.indexOf("b") >= 0) str = str.bold(); if (format.indexOf("i") >= 0) str = str.italics(); if (format.indexOf("f") >= 0) str = str.fixed(); } if (size != null) str = str.fontsize(size); if (color != null) { var colorstr = color.toString(); str = str.fontcolor(colorstr); } } return str; } The Text object contains a text string, along with optional font size, font color, and format information. The format string can contain any combination of the letters "b," "i," or "f," corresponding to bold, italic, or fixed (<tt>) formatting. Text objects mimic some JScript string behaviors--they have a length property and a substring() method.

Listing 16.10 shows the Static object.

Listing 16.10 The Static Object Constructor


function Static (body, text) { this.body = body; this.text = text; this.toString = StaticString; return this; } function StaticString () { return `<html>' + this.body + this.text + `</body></html>'; } The Static object holds a BodyColor object and any text, including HTML, that is to appear between the body and /body tags. Its toString() method returns a complete HTML page ready for display. Now you can also create a new helper function, center(), to center the text on the page, as follows: function center (text) { return `<table width=100% height=100% border=0 ` + `cellpadding=0 cellspacing=0>' + `<tr><td align="center" valign="center">' + text + `</td></tr></table>'; } The center() function accepts a text parameter, which can be either a JScript string or any object that has a toString() method. The function returns the text embedded in a one-cell table with width and height set to 100 percent, and horizontal and vertical centering specified. This way, the text is centered within the frame. To generate random colors for the display, create two new objects, called DarkColor and LightColor, as shown in Listing 16.11.

Listing 16.11 The DarkColor and LightColor Object Constructors


function DarkColor () { this.red = Math.round (127 * rand.next()); this.green = Math.round (127 * rand.next()); this.blue = Math.round (127 * rand.next()); this.toString = ColorString; return this; } function LightColor () {

this.red = Math.round (127 * rand.next()) + 128; this.green = Math.round (127 * rand.next()) + 128; this.blue = Math.round (127 * rand.next()) + 128; this.toString = ColorString; return this; } As you know, color component values can range from 0 to 255. The DarkColor() constructor generates a random color, each of the components of which has a value between 0 and 127. The LightColor() constructor generates a random color with component values between 128 and 255. When used together to create foreground and background colors, DarkColor and LightColor almost always produce a readable combination, though it may not always be an attractive combination. The DarkColor and LightColor objects have an internal structure that is identical to that of the Color object, so they can be used anyplace a Color object can be used. Therefore, it is convenient to think of DarkColor and LightColor as simply being different constructors for a Color object. Now, you can modify the phrase() function to return a complete HTML page, including random foreground and background colors, font size, and format. The modified function is shown in Listing 16.12. Note that in another application, placing the phrase- generation and page-generation code in separate functions might make sense; but for this example, a single function will do. This code is part of the CD-ROM file c16phr.htm.

Listing 16.12 c16phr.htm--The Modified phrase() Function Returns a Complete Page


function phrase (adjs) { var size = "" + (Math.round(rand.next() * 3) + 4); var format = " "; if (rand.next() >= .5) format += "b"; if (rand.next() >= .5) format += "i"; if (rand.next() >= .5) format += "f"; var body; if (rand.next() >= .5) body = new BodyColor (new DarkColor(), new LightColor()); else body = new BodyColor (new LightColor(), new DarkColor()); var plural = (rand.next() >= .5); var vb = verb.toString(); var first = vb.charAt(0);

var vb = first.toUpperCase() + vb.substring(1,vb.length); var art = article.toString(); var adj = new Object(); for (var i = 0; i < adjs; i++) adj[i] = adjective.toString(); var nn = (plural) ? pluralNoun.toString() : singularNoun.toString(); if (plural && art == "a") art = "some"; if (art == "a") { if (adjs > 0) first = adj[0].charAt(0); else first = nn.charAt(0); if (isVowel(first)) art = "an"; } var ph = vb + " " + art + " "; for (i = 0; i < adjs; i++) ph += adj[i] + " "; ph += nn; var screen = new Static (body,center(new Text(ph,size,format))); return screen.toString(); } First, you generate a random font size from 4 to 7. Smaller fonts can be difficult to read, especially when shown in a fixed-width (<tt>) font or italics. Besides, the generated phrase is the only text in its frame, so you might as well make it big. Next, you choose format specifiers. Note that you start with a string containing a single space. This is a workaround for the fact that the indexOf() method call in the Text object may generate an alert if it is called for an empty string. (It should simply return -1, indicating the substring was not found.) For each format specifier, you generate a random number to determine whether it will be included. Testing for greater than or equal to .5 means you have a 50-50 chance that any specifier will be included. You then decide whether to use a dark-on-light or light-on-dark color scheme, again by generating a random number and comparing it to .5. Note that you specify only the foreground and background colors in the BodyColor() constructor because you aren't using any links. At the end of the phrase() function, you create a Static object, using the generated BodyColor object, and a centered Text object that includes the generated font size and format specifiers in addition to the generated phrase. You call the Static object's toString() method directly to return the completely formatted HTML page.

All that's left now is to provide a button so the user can request a new phrase and a selection list enabling the user to specify the number of adjectives to use in the phrase. You put these controls in a separate control frame (named head), as shown in Listing 16.13. This code will also be found in the CD-ROM file c16phr.htm.

Listing 16.13 c16phr.htm--The Control Frame


function printPhrase () { var adj = self.head.document.cont.adj.selectedIndex; if (adj == 3) adj = Math.round (rand.next()*2); self.body.location = "javascript:parent.phrase(" + adj + ")"; } var controlFrame = `<html><body bgcolor="#808080" text="#FFFFFF">' + `<form name="cont">' + `<table width=100% height=100% border=0 cellpadding=0 cellspacing=0>' + `<tr align="center">' + `<td colspan=2><b>Number of Adjectives</b> <select name="adj">' + `<option>None' + `<option>1' + `<option>2' + `<option selected>Random' + `</select></td>' + `<td colspan=2><input type="button" value="Generate Phrase!" ` + `onclick="parent.printPhrase()"></td>' + `</tr>' + `</table>' + `</form>' + `</body></html>'; When the user presses the Generate Phrase! button, the printPhrase() function is called. This function determines how many adjectives to use by examining the selectedIndex property of the selection list, adj. If the user has selected the fourth option, Random, a random value between 0 and 2 is calculated. Then the frame where you show the phrase, body, is updated by using a javascript: URL that calls the phrase() function. The complete Listing of the phrase generator is included on the CD-ROM in file c16phr.htm. Figure 16.3 shows an example of the output. Figure 16.3 The random phrase generator at work.

Adding and Sorting Words

The phrase generator can produce some pretty amusing results just as it is, but sooner or later, users will want to get into the act and add some words of their own. They also will want to see which words are already defined. In this section, you extend the Word object so that it can accept additional words and produce a sorted (alphabetized) list of its contents. You also add some additional controls to the control (head) frame so that the users can view and add words. You start by taking a look at the sorting function. Many sorting algorithms are available. The simplest to comprehend and write is the bubble sort. The bubble sort algorithm makes n - 1 passes through a list of n items, comparing and, if necessary, exchanging adjacent pairs. After the last pass, the list is sorted. Unfortunately, the bubble sort is also just about the slowest sorting algorithm available. If you're sorting only a handful of items, it doesn't make much difference which algorithm you use. But if you are sorting dozens or hundreds of items, or more, that difference becomes very significant. It could mean the difference between waiting a fraction of a second or a couple of minutes for your sort to complete. Fortunately, much faster algorithms are available, and although they're not as easy to comprehend, you can implement them using only a little more code than a bubble sort. One of the best is the Quicksort algorithm. We won't get into the details of its operation in this chapter, except to say that it takes a divide-and-conquer approach to its comparisons and exchanges. The JScript Quicksort algorithm shown in Listing 16.14 was written by Achille Hui of Stanford University.

Listing 16.14 A JScript Quicksort Implementation


function _pm_array_qsort(vec,lo,up,cmp_fun){ var i, j, t; while(up > lo){ i = lo; j = up; t = vec[lo]; while(i < j){ while(cmp_fun(vec[j],t) > 0) j -= 1; vec[i] = vec[j]; while((i < j) && (cmp_fun(vec[i],t) <= 0)) i++; vec[j] = vec[i]; } vec[i] = t; if(i - lo < up - i){ _pm_array_qsort(vec,lo,i-1,cmp_fun); lo = i+1;

} else { _pm_array_qsort(vec,i+1,up,cmp_fun); up = i-1; } } } function _pm_array_defcmp(a,b){ return (a == b) ? 0 : (a > b) ? 1 : -1; } function pm_array_qsort(vec,lo,hi,cmp_fun){ if(vec == null){ return; } else if(cmp_fun == null){ _pm_array_qsort(vec,lo,hi,_pm_array_defcmp); } else { _pm_array_qsort(vec,lo,hi,cmp_fun); } } To use this Quicksort, call the pm_array_qsort() function, passing it an array object (vec), the starting item number in the array (lo), the ending item number (hi), and optionally, a comparison function (cmp_fun). The lo and hi parameters you use depend on how your array object is constructed. If you use the first entry (entry[0]) to contain the array length, for instance, then you should pass 1 as the lo parameter and the number of entries in the array as the hi parameter. If you use a zero-based array, then you should pass 0 as the lo parameter, and the number of entries minus one as the hi parameter. Your Quicksort function includes a default comparison function, which is used to compare two items. The default comparison function can be used if your array consists of strings or numeric items. If you are sorting an array of objects, however, you need to supply a comparison function. The comparison function compares two items, a and b. If they are equal, it returns 0. If a is greater than b, then the function returns 1. If a is less than b, it returns -1. Now, you can beef up your Word object, as shown in Listing 16.15. The improved Word object will let you add new words, sort the words in the object, produce a list of sorted words, and find a particular word.

Listing 16.15 An Improved Word Object Constructor


function Word () { var argv = Word.arguments; var argc = argv.length; this.list = new Object(); for (var i = 0; i < argc; i++) this.list[i] = argv[i];

this.count = argc; pm_array_qsort (this.list,0,this.count-1); this.add = AddWord; this.find = FindWord; this.print = PrintWords; this.toString = WordString; return this; } function AddWord (str) { this.list[this.count++] = str; pm_array_qsort(this.list,0,this.count-1); } function FindWord (str) { for (var i = 0; i < this.count; i++) if (this.list[i] == str) return i; return -1; } function PrintWords () { var str = ""; for (var i = 0; i < this.count; i++) str += this.list[i] + `<br>'; return str; } The Word() constructor calls the pm_array_qsort function to sort the original list of words supplied when the object is constructed. You could keep them unsorted instead, and sort them only when output is required. In this case, the design decision is arbitrary, but sometimes it is desirable to maintain an array in sorted form at all times. The add() method, AddWord(), adds a new word to the end of the array and then sorts the array back into alphabetical sequence. The find() method, FindWord(), searches the array to see whether a word is present. You use this method in conjunction with the add() method to prevent the user from adding duplicate words. The print() method, PrintWords(), returns the sorted list of words, separated by HTML <BR> tags. In Listing 16.16, you add some functions that prompt the user for a new word. You also add functions to list all the words for each type.

Listing 16.16 Functions to Prompt the User and List Words


function addVerb () {

var str = prompt ("Enter a verb (eat, kiss, bite, etc.):",""); if (str == null || str == "") return; if (verb.find(str) != -1) { alert ("\nThat verb is already listed!"); return; } verb.add(str); listVerbs(); } function addAdjective () { var str = prompt ("Enter an adjective (pretty, smelly, nice, etc.):",""); if (str == null || str == "") return; if (adjective.find(str) != -1) { alert ("\nThat adjective is already listed!"); return; } adjective.add(str); listAdjectives(); } function addSingular () { var str = prompt ("Enter a singular noun (dog, cat, knife, etc.):",""); if (str == null || str == "") return; if (singularNoun.find(str) != -1) { alert ("\nThat noun is already listed!"); return; } singularNoun.add(str); listSingular(); } function addPlural () { var str = prompt ("Enter a plural noun (dogs, cats, knives, etc.):", ""); if (str == null || str == "") return; if (pluralNoun.find(str) != -1) { alert ("\nThat noun is already listed!"); return; } pluralNoun.add(str); listPlural(); }

function listVerbs () { self.body.location = "javascript:parent.showList(`Verbs',parent.verb.print())"; } function listAdjectives () { self.body.location = "javascript:parent.showList(`Adjectives',parent.adjective.print())"; } function listSingular () { self.body.location = "javascript:parent.showList(`Singular Nouns',parent.singularNoun. print())"; } function listPlural () { self.body.location = "javascript:parent.showList(`Plural Nouns',parent.pluralNoun.print ())"; } function showList (title,str) { return `<html><body bgcolor="#FFFFFF" text="#0000FF"><h1 align="center">' + title + `</h1><div align="center"><font size=5>' + str + `</font></div></body></html>'; } The addVerb(), addAdjective(), addSingular(), and addPlural() functions prompt the user for a word. If the word is already present in the list, an error message is displayed. Otherwise, the word is added, and the updated list is displayed. The listVerbs(), listAdjectives(), listSingular(), and listPlural() functions display the word lists by updating the body frame location using a javascript: URL. This URL includes a call to the showList() function, which returns a formatted HTML page listing the words for the given word type. Finally, you update the control frame to include a set of buttons for adding and listing words, as shown in Listing 16.17.

Listing 16.17 The Updated Control Frame


var controlFrame = `<html><body bgcolor="#808080" text="#FFFFFF">' + `<form name="cont">' + `<table width=100% height=100% border=0 cellpadding=0 cellspacing=0>' + `<tr align="center">' +

`<td colspan=2><b>Number of Adjectives</b> <select name="adj">' + `<option>None' + `<option>1' + `<option>2' + `<option selected>Random' + `</select></td>' + `<td colspan=2><input type="button" value="Generate Phrase!" ` + `onclick="parent.printPhrase()"></td>' + `</tr>' + `<tr align="center">' + `<td><input type="button" value="Add Verb" ` + `onclick="parent.addVerb()"></td>' + `<td><input type="button" value="Add Adjective" ` + `onclick="parent.addAdjective()"></td>' + `<td><input type="button" value="Add Singular Noun" ` + `onclick="parent.addSingular()"></td>' + `<td><input type="button" value="Add Plural Noun" ` + `onclick="parent.addPlural()"></td>' + `</tr>' + `<tr align="center">' + `<td><input type="button" value="List Verbs" ` + `onclick="parent.listVerbs()"></td>' + `<td><input type="button" value="List Adjectives" ` + `onclick="parent.listAdjectives()"></td>' + `<td><input type="button" value="List Singular Nouns" ` + `onclick="parent.listSingular()"></td>' + `<td><input type="button" value="List Plural Nouns" ` + `onclick="parent.listPlural()"></td>' + `</tr>' + `</table>' + `</form>' + `</body></html>'; The complete listing of the improved phrase generator is included on the accompanying CD-ROM in file c16phr2.htm. One example result after adding the adjective "spongy" is shown in Figure 16.4. Figure 16.4 The improved phrase generator includes controls to add and view words.

An Online Bookstore
In this section, you develop an online bookstore application. You create a small database of books and provide a way for the user to look up books by subject, author, or title. Along the way, you learn how to parse free-form user input and how to look up items in an indexed database.

Of course, in real life, you can't expect to keep the entire inventory of a bookstore in a single JScript document. But the techniques you develop here can be applied to many smaller databases or to results returned by a CGI program on the server.

Parsing Free-Form User Input


Usually, when you process input entered in a text field, the value is treated as a whole. If you are expecting a numeric value, you might check to ensure that the value is, indeed, numeric. You might also check to see that it falls within a certain range or ranges. If you expect an alphanumeric value, you might check it against a list of expected values. But suppose you want to allow the user to enter a series of values in a single field but process the values individually? A good example is a database lookup or search function, where the user can enter a set of keywords. In that case, you need to parse the input field, that is, break it into a list of individual words or terms. The process of parsing is fairly straightforward. The first step is to define the whitespace characters that can separate the terms in your input field. Whitespace is usually defined as blank, or space, characters, and tabs. It may also include carriage returns and linefeeds, as well as certain other nondisplaying characters. The isWhitespace() function shown in Listing 16.18 decides whether the input character is whitespace.

Listing 16.18 The isWhitespace() Function


function isWhitespace (ch) { if (ch == ` ` || ch == `\n' || ch == `\r' || ch == `\t' || ch == ` \f' || ch == `\v' || ch == `\b') return true; return false; } You may also want to test for certain delimiter characters. Common delimiters include commas, forward or backward slashes, periods, and so on. Delimiters can be a meaningful part of the input, or they can be nonessential characters that can be discarded. The isDelimiter() function shown in Listing 16.19 tests for delimiters.

Listing 16.19 The isDelimiter() Function


function isDelimiter (ch) { if (ch == `,' || ch == `?' || ch == `-' || ch == `.' ||

ch == `\\' || ch == `/') return true; return false; } After you decide which whitespace and delimiter characters can separate your terms, you need a place to put the individual terms you extract from the input field. A simple array can do the trick. In this case, you can define a KeywordList object to hold them, shown in Listing 16.20. This object will come in handy in the bookstore example.

Listing 16.20 The KeywordList Object Constructor


function KeywordList () { this.count = 0; this.word = new Object (); this.add = AddKeyword; return this; } function AddKeyword (word) { for (var i = 0; i < this.count; i++) if (this.word[i] == word) return; this.word[this.count++] = word; } In the bookstore example, you want to allow only unique keywords. Therefore, the add() method, AddKeyword(), prevents duplicate keywords from being added. However, this method would not be appropriate in many applications. If you don't want to suppress duplicates in your application, then omit the first three lines in the body of the AddKeyword() function. Now you're ready to write the parser itself, shown in Listing 16.21.

Listing 16.21 The parseKeywords() Function


function parseKeywords (str) { var list = new KeywordList (); var inword = false; var word = ""; var len = str.length; for (var i = 0; i < len; i++) { var ch = str.charAt(i); if (isWhitespace(ch) || isDelimiter(ch)) { if (inword) { list.add(word); word = "";

inword = false; } } else { word += ch; inword = true; } if (i + 1 == len && inword) list.add(word); } return list; } The parseKeywords() function accepts a string, which can be the contents of an input field. It returns a KeywordList object, containing a list of the extracted terms. The parseKeywords() function examines each character in the input string to decide whether it is a whitespace or delimiter character. If it is not, the character is added to the current word. If so, the current word, if any, is added to the list, and preparation is made for a new word. You also add the current word to the list when you reach the last character of the input string. The parseKeywords() function discards delimiter characters because they are not important to the bookstore application. However, delimiters can have special meaning to your application, in which case you might want to add them to the keyword list.

Building an Index
For the example, you want users of your online bookstore to be able to look up books by title, author, or subject. To do so, you must build some indexes for the book database. You use JScript's associative array feature to create the indexes. Associative arrays enable you to associate a value with an array entry. You can then use that value to retrieve the desired entry. For example, suppose that you create a simple array named animal and associate a name with each entry, as follows: var animal = new Object(); animal["dog"] = "Woof!"; animal["cat"] = "Meow!"; animal["pig"] = "Oink!"; To retrieve an item you use the value associated with it, as follows: document.write("A dog says " + animal["dog"] + "<br>"); To take advantage of this capability, you index each word in the book titles, subjects, and author

names by creating an entry in an associative array. The only hitch is that you can have only one entry per value. What if, as is very likely, more than one of the books uses that value in its title, subject, or author? The solution, as it turns out, is fairly simple. Instead of associating an individual book object with each entry in the array, you create a special object that contains a list of the items that match a given value and associate that object with the value. Listing 16.22 shows the index object, along with its methods and the internal list object:

Listing 16.22 The Index and IndexItemList Object Constructors


function IndexItemList () { this.count = 0; this.item = new Object(); this.add = AddIndexItem; return this; } function AddIndexItem (object) { this.item[this.count++] = object; } function Index () { this.count = 0; this.item = new Object(); this.add = AddToIndex; return this; } function AddToIndex (object, keywords) { for (var i = 0; i < keywords.count; i++) { var kw = keywords.word[i]; var ilist = this.item[kw]; if (ilist == null) { ilist = new IndexItemList(); this.item[kw] = ilist; } ilist.add(object); } } The IndexItemList object is used internally to store a list of objects that contain a particular keyword value. In the bookstore example, it will contain references to one or more Book objects (which you define shortly) that share a given keyword. The IndexItemList object has a single method, AddIndexItem(). You don't need to access the IndexItemList object directly. The Index object contains the associative array, item. This array contains a list of

IndexItemList objects. Each entry in the array is associated with a value, in this case a keyword. The Index object includes a method to add items to the array. You will write another method to look up entries shortly. The Index object's add() method, AddToIndex(), accepts an object to be indexed and a list of keywords in the form of a KeywordList object. For each keyword in the KeywordList, AddToIndex() first checks to see whether an IndexItemList object is associated with the keyword. Note that it uses the keyword value itself as an index into the array. If no IndexItemList object exists for the keyword, a new object is created and added to the array, again using the keyword as the index. Finally, the object to be indexed is added to the IndexItemList for that keyword value. This process is repeated for each keyword, so a given object can have several index entries.

Defining Book and Catalog Objects


Now you're ready to create the Book object. In Listing 16.23, you also create a Catalog object that contains a list of all books, plus subject, title, and author indexes.

Listing 16.23 The Book and Catalog Object Constructors


function Book (author, title, subject, code, price) { this.author = author; this.title = title; this.subject = subject; this.code = code; this.price = price; return this; } function Catalog () { this.count = 0; this.book = new Object; this.author = new Index(); this.title = new Index(); this.subject = new Index(); this.add = AddToCatalog; return this; } function AddToCatalog (book) { this.book[this.count++] = book; this.author.add(book,parseKeywords(book.author)); this.title.add(book,parseKeywords(book.title)); this.subject.add(book,parseKeywords(book.subject)); } The Book() constructor simply creates an object containing each of the relevant pieces of

information about the book. The Catalog() constructor creates a simple array, book, which contains a single entry for each book. It also creates three Index objects: author, title, and subject. The Catalog object's add() method, AddToCatalog(), does the really interesting work. First, it adds the book object to the book array. Next, it updates the author, title, and subject indexes. For each of the indexes, it calls the parseKeywords function to create a list of keywords from the value of the field. The Index object's add() method then creates an index entry for each of these values. In Listing 16.24, you create a catalog and add some books to it.

Listing 16.24 Creating a Catalog and Adding Books


var cat = new Catalog(); cat.add (new Book ("Kingsolver, Barbara", "Animal Dreams", "fiction animals dreams environment Native-American love", "ISBN 0-06-092114-5", 13.00)); cat.add (new Book ("Calasso, Roberto", "The Marriage of Cadmus and Harmony", "fiction Greek myth mythology Zeus Athens", "ISBN 0-679-73348-5", 13.00)); cat.add (new Book ("Le Carre, John", "The Night Manager", "fiction suspense spy arms drugs", "ISBN 0-345-38576-4", 6.99)); cat.add (new Book ("Rice, Anne", "Interview with the Vampire", "fiction vampire New Orleans gothic horror", "ISBN 0-345-33766-2", 4.95)); cat.add (new Book ("Garcia Marquez, Gabriel", "One Hundred Years of Solitude", "fiction South America magic dreams war love", "ISBN 0-06-091965-5", 13.00)); cat.add (new Book ("Barkakati, Naba", "Object-Oriented Programming in C++", "nonfiction computer language programming object C", "ISBN 0-672-22800-9", 29.95)); cat.add (new Book ("Petzold, Charles", "Programming Windows", "nonfiction computer programming C windows", "ISBN 1-55615-264-7", 29.95)); Well, so far so good. You've got a catalog loaded up with books, and they're all cross-referenced by author, subject, and title. But how do you use this information? What you need now is a search mechanism. You want the search to return multiple matches for a

given set of keywords. Also, ideally, the results should be ranked by how well they match the keywords supplied. To accomplish this task, you first create an object to hold a list of search results, as shown in Listing 16.25.

Listing 16.25 The Result and ResultList Object Constructors


function Result (object, score) { this.object = object; this.score = score; return this; } function ResultList () { this.count = 0; this.item = new Object(); this.add = AddResult; this.sort = SortResults; return this; } function AddResult (object) { for (var i = 0; i < this.count; i++) if (this.item[i].object == object) { this.item[i].score++; return; } this.item[this.count++] = new Result (object,1); } function SortResults () { pm_array_qsort (this.item,0,this.count - 1,CompareResults); } function CompareResults (a,b) { return (a.score == b.score) ? 0 : (a.score < b.score) ? 1 : -1; } The Result object holds an individual object--in this case, a Book object. It also contains a score field. This field indicates the number of "hits" the query gets for this particular object, that is, how many of the keywords specified in the query match this object. The ResultList object contains a list of Result objects. It contains one Result for each object (book) that matches one or more of the specified keywords. The add() method, AddResult, searches the ResultList for a matching object. If it finds one, it increments the score by one. Otherwise, it creates a new Result entry for the object and sets the score to one. The sort() method, SortResults(), sorts the Result objects in the ResultList in

descending order according to score. That is, the objects with the highest score go to the top of the list. Because you are sorting objects rather than simple strings or numbers, you must supply a comparison function, CompareResults, to the pm_array_qsort() function. Now, you can add the search function. In Listing 16.26, you update the Index object to make SearchIndex() the find() method.

Listing 16.26 Adding a find() Method to the Index Object


function Index () { this.count = 0; this.item = new Object(); this.add = AddToIndex; this.find = SearchIndex; return this; } function SearchIndex (keywords) { var rlist = new ResultList(); for (var i = 0; i < keywords.count; i++) { var kw = keywords.word[i]; var ilist = this.item[kw]; if (ilist != null) for (var j = 0; j < ilist.count; j++) rlist.add(ilist.item[j]); } rlist.sort(); return rlist; } The find() method, SearchIndex(), takes a KeywordList object containing a list of words to search for. It first uses the keyword value to do an associative array lookup to retrieve the IndexItemList object, if any, for the given keyword. Then, it calls the ResultList object's add() method to add each matching object to the result list, or increment the score for that object if it was already added to the list. This process is repeated for each search term specified. Finally, the ResultList is sorted by score and returned to the caller.

The Bookstore
You've got all the tricky pieces worked out, so you can build an interface and open your bookstore. You can make a control frame with a selection list for author, title, or subject, and a text field for keyword entry. A Search button starts the search. In Listing 16.27, you write some functions to process this information and display the results.

Listing 16.27 Creating the Bookstore Interface

var controlFrame = `<html><body bgcolor="#808080" text="#FFFFFF">' + `<form name="cont">' + `<table border=0 width=100% height=100% cellpadding=0 cellspacing=0>' + `<tr align="center" valign="center">' + `<td><b>Search by: </b><select name="stype">' + `<option selected>Title' + `<option>Author' + `<option>Subject' + `</select></td>' + `<td><b>Keywords: </b><input size=30 name="keywords"></td>' + `<td><input type="button" value="Search" onclick="parent.doSearch ()"></td>' + `</tr></table>' + `</form>' + `</body></html>'; var results = null; function doSearch () { var index = self.head.document.cont.stype.selectedIndex; var keywords = parseKeywords (self.head.document.cont.keywords. value); if (index == 0) results = cat.title.find (keywords); else if (index == 1) results = cat.author.find (keywords); else results = cat.subject.find (keywords); self.body.location = "javascript:parent.showList()"; } function showBook (item) { var book = results.item[item].object; var detail = book.author + `<br>' + book.title + `<br>' + book.subject + `<br>' + book.code + `<br>$' + book.price + `<br>' + `<h3><a href="javascript:parent.showList()">Return to list</h3>'; return `<html><body bgcolor="#FFFFFF" text="#000000" link="#0000FF" ` + `alink="#FF0000"><div align="center"><table border=0><tr><td>' + detail + `</td></tr></table></body></html>'; } function showList () { var list = ""; for (var i = 0; i < results.count; i++)

list += `<a href="javascript:parent.showBook(` + i + `)">' + `(` + results.item[i].score + `)&nbsp&nbsp' + results.item[i].object.author + `:&nbsp&nbsp' + results.item[i].object.title + `</a><br>'; if (list.length == 0) list = `<h2 align="center">Sorry, no matches found</h2>'; return `<html><body bgcolor="#FFFFFF" text="#000000" link="#0000FF" ` + `alink="#FF0000"><div align="center"><table border=0><tr><td>' + list + `</td></tr></table></body></html>'; } Clicking the Search button calls the doSearch() function. This function examines the selection list and performs the appropriate search. The result list is placed in a global variable called results. The doSearch() function then loads the show frame with a javascript: URL that calls showList(). The showList() function, in turn, reads the result list and creates a one-line entry for each book, consisting of the score (number of matching terms), along with the book's author and title. Each entry is enclosed in an HREF that calls the showBook() function to display details about the book. The showBook() function displays each of the fields in the Book object. It also includes an HREF back to the showList() function so that the user can return to the result list of the current search. That's it! Your bookstore is open for business. The complete listing is included on the accompanying CD-ROM in file c16book.htm. Figure 16.5 shows the resulting list of titles based on a subject search of the keyword love, and Figure 16.6 shows the complete author, title, and subject information for one book. Figure 16.5 Each book matching the search term is listed. Figure 16.6 Selecting a book shows a detailed listing.

Improved Indexing and Searching


The indexing and searching algorithms do a good job of finding matching entries, but they suffer from a couple of drawbacks. First, the user must enter keywords exactly as they were specified when the Book object was created. One obvious improvement is to store all keywords in lowercase and convert search words to lowercase before beginning the search.

But what if the user enters the plural or past tense version of a word? What if the user includes (or fails to include) apostrophes, quotation marks, or other punctuation symbols? The search engine will break down and fail to return any matching items. You can address this problem to some extent by normalizing all keywords before adding them to the index or performing a lookup. Normalizing a word means reducing it to something akin to a root word. This process is not easy; volumes have been written and fortunes spent on developing effective indexing and searching algorithms. But you can use a few simple techniques to improve your search results dramatically. First, create a function to normalize a word, as shown in Listing 16.28.

Listing 16.28 The normalizeWord() Function


function normalizeWord (keyword) { var esc = escape (keyword.toLowerCase()); var kw = ""; for (var i=0; i < esc.length; i++) { var ch = esc.charAt(i); if (ch == `%') i += 2; else kw += ch; } var len = kw.length; if (kw.charAt(len-1) == "s" && kw.charAt(len-2) != "s") { kw = kw.substring(0,len-1); len--; } if (kw.substring(len-2,len) == "ly") { kw = kw.substring(0,len-2); len -= 2; } if (kw.substring(len-2,len) == "ed") { kw = kw.substring(0,len-1); len--; } if (kw.substring(len-2,len) == "er") { kw = kw.substring(0,len-1); len--; } if (kw.substring(len-2,len) == "ie") { kw = kw.substring(0,len-2) + "y"; len--; }

if (kw.substring(len-3,len) == "ing" && len > 5) { kw = kw.substring(0,len-3); len -= 3; if (isVowel(kw.charAt(len-2)) && !isVowel(kw.charAt(len-3))) { kw += "e"; len++; } } if (kw.charAt(len-1) == "e") if (!isVowel(kw.charAt(len-3))) { kw = kw.substring(0,len-1); len--; } if (len > 1 && (kw.charAt(len-1) == kw.charAt(len-2))) { kw = kw.substring(0,len-1); len--; } return kw; } The normalizeWord() function starts by converting the keyword to lowercase. Next, it strips out any punctuation marks or other unusual characters. To strip the characters, it calls JScript's escape () function, which converts all unusual characters to a percent sign (%) followed by two ASCII characters. These characters are then removed. The normalizeWord() function then makes a series of transformations based on the word ending. Note that the order of these transformations is important. We won't go into detail on each transformation here. The goal is to reach a root version of the word. It isn't necessarily the true English root, but as long as you perform the same transformations on both the indexed words and the search words, you should improve chances of getting a match. NOTE: The transformations applied by the normalizeWord() function are useful only for English words. The call to escape() strips out accented letters, for instance, and the word ending transformations are meaningful only for English words. However, creating a similar function for other languages should be possible.

The other problem with this indexing scheme is that it indexes and searches for many words that are extraneous, such as "the," "and," "a," and so on. Most indexing and searching programs use a list of stop words to exclude extraneous words. These lists are often quite extensive, but you can write a simple function to deal with the worst offenders. Listing 16.29 shows a simple isStopword() function.

Listing 16.29 The isStopword() Function

function isStopword (word) { var wd = word.toLowerCase(); if (wd == "a" || wd == "an" || wd == "and" || wd == "or" || wd == "the") return true; return false; } Finally, you can modify the parseKeywords() function to call normalizeWord() and isStopword(), as shown in Listing 16.30.

Listing 16.30 The Improved parseKeywords() Function


function parseKeywords (str) { var list = new KeywordList (); var inword = false; var word = ""; var len = str.length; for (var i = 0; i < len; i++) { var ch = str.charAt(i); if (isWhitespace(ch) || isDelimiter(ch)) { if (inword) { if (!isStopword(word)) list.add(normalizeWord(word)); word = ""; inword = false; } } else { word += ch; inword = true; } if (i + 1 == len && inword) if (!isStopword(word)) list.add(normalizeWord(word)); } return list; } The improvements made here are included in file c16book2.htm on the CD-ROM. You can try this more sophisticated code by doing a subject search for "the love." The results which you will obtain will be identical to those shown in Figure 16.5, since the stop word "the" has been removed. A number of additional improvements could be made, including better handling of symbols, and Boolean AND and OR operations, to name a few.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Chapter 11 More About Java


q q

Chapter 11 More About Java r The Java Class Hierarchy s Classes and Subclasses s Listing 11.1 s A Class Method Calls Its Superclass Method s Packages in Java s Listing 11.2 s The Structure of a Runnable Java Applet s Listing 11.3 s An Example of Hierarchical Layout in Java r A Pop-Up Document Viewer Applet s Listing 11.4 s SD.java--Viewing a Document in a New Browser Window Using Java s Initializing the SD Applet s Event Handling in the SD Applet s Opening a New Document with the SD Applet r An Image Viewer Applet s Listing 11.5 s Simimg.java--Displaying Multiple Images Is Easy Using Java Threads s Initializing the Simple Image Viewer s Listing 11.6 s Simimg.htm--HTML for the Simimg Applet s Running the Simple Image Applet

More About Java


Some of the main topics in this chapter are
q q q q

Using Java packages Loading and displaying Images in Java Laying out components in the applet window Manipulating URLs

One of the major advantages of the Java language is its power and flexibility. Java is a full-featured programming language with all the constructs one needs to develop object-oriented applications. However, as you have already seen in Chapter 10, "A Java Tutorial," Java is not as directly connected with the environment of its Web page as JScript is. Java cannot readily access HTML elements on a Web page in a direct manner. As compensation for this deficiency, Java provides some extremely powerful tools for manipulating images and URLs. Java also has a set of components, known as the Advanced Windowing Toolkit (AWT), which enables Java applets to create pushbuttons, text entry fields, and other HTML-like entities. The term Java encompasses many things. In Chapter 10, we focused on gaining some initial understanding of Java as a programming language. In the process, you encountered some old, familiar methods, such as parseInt() and charAt(), and also some new ones, such as paint (). This points to the fact that Java is more than a language. Java is also a set of methods, organized into a collection known as the Java Class Hierarchy, which enables us to do complex tasks. Much of the expressiveness of Java becomes clear only when we learn more about some of the components of the Java Class Hierarchy and what they can do for us. This chapter explores the Java Class Hierarchy with particular emphasis on image and URL manipulation. It presents the basic concepts necessary to explore Java further and enables you to write more complex and interesting Java applets.

The Java Class Hierarchy


In Chapter 10 you were first exposed to the concept of inheritance in Java. In particular, in the applet described in the section "An Accounting Applet in Java" you saw three Java classes working together: the Account class, the Acex class, which drove the applet itself, and, implicitly, the Java class java. applet.Applet. You were introduced to the special keyword extends, and we saw that Acex was said to extend the built-in class java.applet.Applet. This idea of having one class extend another, also known as subclassing, is critical to understanding the Java Class Hierarchy. See "An Accounting Application in Java," in Chapter 10, "A Java Tutorial," for a detailed example of subclassing the Applet class.

Classes and Subclasses


In Chapter 10, we built our Account class from the ground up and gradually refined the methods to perform a set of simple but useful operations. We could have continued this process ad infinitum, adding more and more functions for more and more specialized situations. This would make the Account class cover a larger number of situations, but it would also lead to dramatic overkill in some cases. It would be nice to have the capability to handle escrow accounts, foreign currency transactions, and the like, but in many situations you would not use these extra capabilities. This leads to the notion that perhaps we do not want to extend a class by adding more and more to it,

but rather by creating specialized versions of that class. The spe-cialized versions would have all the capabilities of the generalized class, but would also have their own unique features. The specialized classes, such as EscrowAccount and InternationalAccount, would have all the methods and instance variables of Account, but would also have their own methods, which Account does not have. The specialized classes inherit the attributes of their parent. The specialized classes are subclasses of their parent class, which is known as the superclass.

NOTE: There is no multiple inheritance in Java. Every Java class has exactly one parent class.

Naturally, this simple idea of inheritance acquires some twists and turns when it is actually implemented. The first such variation is the idea of having a subclass override a method in the superclass. The Acex applet discussed at the end of Chapter 10 overrides the paint method of its java.applet.Applet superclass. You can imagine that the international version of Acex would keep the withdraw and balance methods the same and would add convert and transfer methods (to convert between different currencies and to transfer money). It might also override the deposit method so that deposits could be made in foreign as well as local currency. A subclass not only extends its superclass, it also tends to modify its behavior for special situations. Java has a special keyword, super, that is used to refer to the superclass of a class. Superclass instance variables can be accessed as super.varname, and superclass methods can be invoked as super.methodname(). This keyword is particularly useful if you want the subclass to use its own method named NAME and also use its parent's method, also named NAME. For example, our internationalized version of the deposit method might look something like Listing 11.1. This version of deposit simply converts the deposit amount, in any arbitrary currency, into the local equivalent (line 3) and then calls the deposit method in the superclass (Acex) to perform the deposit. This avoids the tedious approach of copying all the deposit code in any subclass that overrides it.

Listing 11.1 A Class Method Calls Its Superclass Method


// Assume that "currency" is a variable specifying the type of currency, // and that convert is a method that converts between currencies // this is the subclass deposit method void deposit(int amount, int which, int currency) { // 1; int localamount; localamount = convert(amount, currency);

// 3; convert to local super.deposit(localamount, which); // 4; invoke superclass method } What happens to instance variables of a class when a subclass is derived from it? As one might imagine, public instance variables remain public. Interestingly enough, private instance variables (and private methods) are completely private--they are unknown in the subclass just as they are unknown outside the class. This means that no subclass can reference private instance variables or make use of private methods of its superclass. Java also has a third category, known as protected variables and methods, which are known to the class and to all its subclasses, but remain invisible outside the class.

Packages in Java
The Java Class Hierarchy is the collection of all the classes that are provided as a standard part of Java. These classes are organized in a class hierarchy, as described above, with a series of very general classes--such as the ubiquitous class known as Object--at the top of this hierarchy. This might lead you to guess that the class java.applet.Applet, which is the superclass of all applets, is a subclass of java.applet, which is in turn a subclass of an all-encompassing java class. This is an excellent guess, but it is incorrect. Java actually has two kinds of organization for its classes. It has a strict class hierarchy, which describes all the children of each class. It also has a more horizontal organizational structure, known as the Java package system. Packages are used to group together similar but not necessarily directly related classes into a set of groups. These groups are the Java packages. Packages can be distinguished notationally from classes because they all begin with a lowercase letter, while classes always start with an uppercase letter. Thus Applet is a class in the java.applet package, which is a part of the java package. As a class, Applet is derived as follows: Object -> Component -> Container -> Panel -> Applet An applet is therefore actually a specialized form of the graphic class Panel, which is derived from two other graphics classes, Container and Component, and ultimately from Object. This is an excellent example of the matrix organization of classes and packages. Applet is a member of the java.applet package; Panel, Container, and Component are members of the java.awt (Advanced Windowing Toolkit) package; and Object is the member of the java.lang package. The top of the Java package hierarchy is the java package. There are other top-level hierarchies, such as the sun hierarchy, which are platform- and/or operating-system-dependent. The java hierarchy, however, is always guaranteed to be present. It contains the following packages:
q q q

lang net awt

q q q

applet util io

The java.lang Package. The java.lang package is one of the most important and fundamental of the java packages. It defines the basic object types that correspond to elements of the language. It also includes several very interesting pieces of machinery that are used throughout Java programming, including the critical concept of a thread, which will be reviewed shortly. The data type classes contained within java.lang include Boolean, Character, and String as well as the numerical types Integer, Long, Float, and Double. These latter four classes are actually subclasses of a generic Number class. As one might expect, each of the numerical types defines conversion methods. You have already see one of these, namely the parseInt method of the Integer class, which is used to convert strings to integers. The Acex applet, which appears in the section "An Accounting Applet in Java" of Chapter 10, "A Java Tutorial," illustrates the use of this method. The java.lang package also contains a class known as Math, which is very similar to the JScript object of the same name. Math provides an expanded set of mathematical operations. The same can be said for the String class, which is a full-fledged class (object) in Java--unlike its implicit counterpart in JScript. Java also provides a second string class within the java.lang package known as StringBuffer. This is used for extensible strings. Whenever you concatenate strings using the plus sign (+) operator, you are actually using a StringBuffer. More precisely, whenever the Java compiler sees an expression that involves merging two strings, it rewrites that expression to use a StringBuffer behind the scenes. Finally, the java.lang package contains two critical classes with enormous utility: System and Thread. The System class provides system-level functionality with a platform- independent interface. The way in which it is actually implemented, of course, depends heavily on the actual platform. You have already seen an example of the System class in the print statement, System. out.println("message"), which sends the string "message", with a subsequent carriage return, to the standard output. Where this output actually goes is, of course, platform-dependent. Threads are the subject of the next section and are used in the "Image Viewer Applet" section at the end of this chapter. Using Java Threads. It is often very useful to do several things at once. Not only does this get more done, it brings everything being done to completion earlier. Of course, in this aspect, most humans are like most computers. It is not really possible to do more than one meaningful thing at a time, such as reading two books at once, but it is often highly desirable (particularly for one's image) to make it appear that way. This is the advantage of modern multitasking. Each user process gets its own set of tiny slices of a single CPU, and the illusion of simultaneous processing is maintained. Most modern operating systems enable you to seem to perform several tasks, such as editing while printing. There are often cases in which it is highly desirable to be able to perform many tasks within a single program. This is particularly true in graphics programs. In attempting to display multiple images, it is advantageous to be working on image 5 while image 4 is being displayed, for example. Java provides such a capability as part of its java.lang package through the medium of the Thread class.

A Java thread is very similar to an ordinary thread in a garment. It has a definite starting point, a definite endpoint, and can weave through the garment in tandem with other threads. A complete description of Java threads is well beyond the scope of this chapter. However, we can examine the general structure of a threaded Java applet. This structure is used in the Image Display applet to realize precisely the goal described above: interleaving graphic operations and other operations. The template for a multithreaded Java applet is shown in Listing 11.2.

Listing 11.2 The Structure of a Runnable Java Applet


public class MTApplet extends java.applet.Applet implements Runnable { Thread mythread = null; // the thread we will create public void init() { // init method, as before ... // initialization stuff goes here } public void start() { // start method, creates thread if ( mythread == null ) { mythread = new Thread(); mythread.start(); } } public void stop() { // stop method, stops thread if ( mythread != null ) { mythread.stop(); mythread = null; } } public void paint( Graphics g ) { // local paint method ... // custom drawing goes here } public void run() { // the work method of the thread ... // the main body of the thread } } This template has several familiar features as well as some new wrinkles. The first thing to notice is that the class declaration for this MTApplet class not only extends java.applet.Applet, as it must, it also "implements Runnable". Runnable is a new type of Java element: a Java interface. An interface, like a superclass, expresses a set of methods. A class, such as MTApplet, which implements this interface, must also implement these methods. In particular, it must implement a run method. The purpose of the run method will become clear in a moment. The MTApplet class has the very familiar init() method, which is used to do whatever initialization is required. This usually involves parsing user parameters accessed via the

getParameter() method. If images are to be manipulated, the init() method is also a good place to begin loading those images. The paint() method is also much as before: It is used to perform our applet-specific drawing operations. These operations are now done in parallel, however, using threads. The start() and stop() methods shown in Listing 11.2 are not templates or placeholders: they are shown in their entirety. The start method examines the instance variable mythread to see if it is null (its initial value). If it is, then the start method creates a new Thread instance by invoking the new operator, and sets mythread to be that instance. The effect of creating a new thread is that there is now one extra task that can be run. This new thread is not yet running, however. The final statement in the start method launches this new thread by saying mythread.start (). This calls the start method of the new thread. The new thread now runs as an independent entity within the applet. The stop method is the mirror image of the start method. It also examines the mythread instance variable. If it is not null, then that thread is halted by calling its stop method. Cleanup is then performed by setting the mythread variable back to null. The interplay between start and stop is such that at most one new thread will be created. If start finds that mythread is not null, it will do nothing. Also, stop ensures that the new thread will never be stopped twice. None of this yet explains how the new thread accomplishes anything, however. The answer to this mystery is provided by the new run() method. When a class implements the Runnable interface, and a new thread is created and set running by that class, its run() method will be entered. In fact, every applet is already a thread, known as the main thread. Unless a new thread is created by instantiating the Thread class, the main thread is the only thread, so there is effectively no parallelism. After the second thread is activated and the run method entered, the new thread can do one set of operations while the main thread is doing something else. This is the key idea behind parallelism in Java. If the run method performs some graphical operations and ends up triggering paint(), the actual drawing is performed in the main thread, while the computations leading up to it are performed in the second thread.

CAUTION: The actual implementation of Java threads is platform-dependent at this time. This is because threads require some cooperation from the underlying operating system, and different operating systems cooperate in different ways. A thread-based applet that works perfectly under Solaris may fail on Windows NT, and vice versa. Applets using threads should be thoroughly tested on all major platform types (UNIX, Windows, and Macintosh).

The java.net Package. The java.net package contains the basic classes and methods that are used

for network communications. This package contains classes representing network connections (sockets), network addresses, and, most significantly, URLs. This might sound like an extremely rich source for interesting Java programming ideas, but the Java security model limits what you can do with this package quite severely. It is worthwhile to review these limitations because they have a significant effect on what is possible and what is not. Every Java applet is activated within the context of a Web page via that page's APPLET tag. This Web page in turn was obtained from some URL and is therefore associated with a particular Web server. We will refer to the Web page that activated the applet as that applet's document, and the server from which that page was obtained as the applet's server. The first restriction on network access within Java is that it is prohibited from opening a network connection to any host other than the applet's server. This means that it is not even possible to make a network connection to the user's own host! The second restriction is that a Java applet can access documents only within the directory hierarchy rooted at the applet's document BASE. These two restrictions combined might seem quite grim, because the set of documents accessible within Java is rendered very small. Fortunately, there are no restrictions on documents that Java can ask its browser to open. This concept is one of the subtleties of Java. Java does not actually implement graphics, network connections, or anything else that impacts the external environment. It has a series of methods where it can ask its browser to do these things for it. When you create a button or open a URL in Java, it is actually the browser that is doing these things for you. Having said all this, there is one very important class in the java.net package that you can (and will) use quite effectively: the URL class. As the name implies, this class is used to construct an abstract representation of a URL. This class has several different constructions, as follows: URL(String) URL(URL, String) URL(String, String, String) URL(String, String, int, String) The first form takes a String, such as the literal http://www.microsoft.com, and attempts to construct a URL instance from it. The second form is used to concatenate a String representing a relative pathname onto an existing URL. This form can be used to descend from the applet's document BASE to an HTML file within its tree. The third and fourth forms are used to build a URL from its component parts. The third form takes a protocol name, such as http, a hostname, such as www.microsoft.com, and a file name, such as INDEX.HTML, and produces a URL from that combination. The fourth form enables you also to explicitly set the port number for those rare cases in which the protocol is not being accessed on its default port. (http is occasionally received on port 1080 or 8080 rather than its default 80, for example.) When we review our two major Java applets later in this chapter, you will see the first two forms of the URL class constructor, and also how one politely asks one's browser to open a "foreign" URL.

The discussion below on the java.applet package also shows how to obtain the URL that corresponds to the applet's document BASE. The Advanced Windowing Toolkit. We have already observed that Java cannot interact directly with HTML elements, unlike JScript. There are no HTML FORM components within the Java Class Hierarchy. This means that Java programmers must construct their own buttons, text entry fields, and the like, if they want such items to be part of their applets. The Advanced Windowing Toolkit (AWT) is Java's set of capabilities for doing this. It is contained within the package java.awt. The classes in the AWT can be subdivided into three categories: display items (such as Button), layouts (such as FlowLayout), and overall graphics items (such as Color and Font). The first category is the largest and includes an extensive set of elements, including the following:
q q q q q q q q q q q q q q q q q

Button--a standard button Checkbox--a button with an on/off indicator CheckboxGroup--a set of option buttons Choice--a pop-up menu of choices Dialog--a pop-up dialog box Frame--an entirely new window Image--a GIF or JPEG image Label--a static text item List--a listbox of items Menu--a menu of items Panel--an organizational item that can contain other items Point--a single pixel Polygon--a region bounded by line segments Rectangle--a rectangular region Scrollbar--a scroll bar, usually associated with a List or TextArea TextArea--an editable text item that can have more than one line, and can be scrolled TextField--a single-line editable text item with fixed size

As you can see from this enumeration, many familiar HTML elements are also present in the AWT. As in HTML, it is quite simple to glue together a set of graphical items in a page, but it is somewhat more difficult to make the presentation attractive and crisp. HTML has a number of markup styles and directives that can be used to control the visual format of various elements, including tables and forms. The means to control where elements are placed, how they are aligned with one another, and how they are sized and spaced is always an issue in graphics programming. This applies to all windowing systems. Java is no exception. The Java AWT has chosen an approach with several different, quite distinct layout styles. Within each style, the display elements that you create, such as Buttons and TextAreas, are placed according to a well-defined system. However, it can still take time to get things looking just the way you want, and if all else fails, you can still programmatically position objects at specific coordinates. TIP:

The default Java layout is FlowLayout with CENTER justification. Use this until you become more comfortable with the AWT.

At present, there are five Java layout styles. Each has its own peculiarities, and you will almost certainly find yourself using a combination of styles once you acquire some skill with the AWT. The Java layout classes are:
q q q q q

BorderLayout CardLayout FlowLayout GridLayout GridBagLayout

The BorderLayout approach is based on the idea of placing elements at one of the four cardinal points--North, South, East, or West--or in the Center. It is often ideal for arranging items in case you would like two or three arranged in a vertical (North, Center, South) or horizontal (West, Center, East) stacking order. BorderLayout is also used with Panels for hierarchical organization of items. If you would like a top row of Buttons and perhaps a Label below, you would create two Panels, place them at the North and South locations in a BorderLayout, and then add the Buttons to the northern Panel, and a Label to the southern Panel. Listing 11.3 shows a code fragment that does just this.

Listing 11.3 An Example of Hierarchical Layout in Java


BorderLayout bl; Button but[]; Panel nopa, sopa; Label la; bl = new BorderLayout(); // 5; create a new BorderLayout instance setLayout(bl); // 6; make it the default layout nopa = new Panel(); // 7; create two new panels sopa = new Panel(); add("North", nopa); // 9; put nopa at the North edge add("South", sopa); // 10; add sopa at the South edge but = new Button[4]; // 11; allocate space for 4 buttons but[0] = new Button("Back"); // 12; create the buttons with various labels but[1] = new Button("Forward"); but[2] = new Button("Home"); but[3] = new Button("Done"); for(int i = 0; i < 4; i++) { // 16; add the buttons to North panel nopa.add(but[i]); // 17; it will default to a FlowLayout la = new Label("Southern Label"); // 18; create new label

sopa.add(la); // 19; add to south Panel } This example begins by allocating a new instance of the BorderLayout class (line 5) and then calling the setLayout method to make this the current layout. Remember that a Java applet is actually a subclass of a Panel, so that the bare call to setLayout on line 6 applies to the Panel containing the entire applet. The next two statements create Panel instances. Note that one can create instances of graphical items all day long, but they are not displayed until they are added to the applet. The North and South Panels are added in lines 9 and 10 using the add method. The add method is overridden in all the layout classes, which means that it has its own distinct syntax for each one. In the case of a BorderLayout, the first argument to add must be one of the five permissible directions. We use North and South to split the applet vertically. The next five lines create four Buttons with some text to name them. Lines 16 and 17 then add those buttons to the North panel. This is accomplished by explicitly invoking the add method of nopa, the North panel instance. If we had mistakenly just used add(but[i]) on line 17, this would have attempted to add these buttons to the entire applet's panel. Lines 18 and 19 create and add a Label to the south Panel in a simi- lar way. NOTE: At the moment, button labels must be text. It is not currently possible to put an image inside a button using the Button class. A subclass of the Button class would have to be written to do this.

The FlowLayout class implements an approach in which elements are added incrementally across one or more rows. Elements can be justified within a given row using LEFT, CENTER (the default), or RIGHT justification. If an element does not fit on a given row, the layout wraps around to the beginning of the next row. FlowLayout is often used for rows of buttons or other components of similar size and shape. As mentioned above, FlowLayout is the default layout for any newly created graphical container (such as a Frame or Panel). The other three layout types are more specialized. CardLayout is used to create slideshow-like presentations. Elements of a CardLayout are presented sequentially rather than displayed simultaneously on the screen. GridLayout lives up to its name. It enables you to position elements based on their row and column location. It is used by first specifying the number of rows and columns to be allocated and then placing individual elements in their desired (row, column) location. GridBagLayout is a much more powerful version of GridLayout. It is also regrettably complex because it is necessary to first construct a description of the layout, using the subsidiary class GridBagConstraints, and then actually build the layout on top of that. The final set of classes in the immense java.awt package is the set of classes that correspond to general graphical constructs rather than things that are actually drawn. We have already seen two examples of these classes in our tiny applets from Chapter 10, "A Java Tutorial:" the Color and

Graphics classes. The Color class is usually used by invoking its static instance variables that name the primary colors (such as Color.Red), although it can also be used to construct arbitrary color values directly from red, green, and blue levels. The Graphics class captures the entire graphical state of an applet. Recall that the method signature for the applet paint() method is public void paint( Graphics g ). Within paint(), you can call a set of methods too numerous to mention to draw strings, rectangles, and other common primitive graphics operations. Some of the other important classes in this general graphics category are the following:
q q q

Event Font MediaTracker

The Event class is extremely important because it enables us to respond to user events, such as a button being pushed inside our applet. The Applet class has another method, known as action(), that is called whenever user interaction takes place. Its method signature is public Boolean action( Event ev, Object arg ). It is called whenever the Object arg (a Button, for example) is pushed and generates the Event ev. If you override the default action method, you can control what happens when events occur, just as in JScript.

CAUTION: Java Events and JScript events are not directly related. At present, Java cannot directly respond to events outside its applet. It is also not possible to install a JScript event handler for Events inside a Java applet.

The Font class is used to manipulate the text appearance of any item that contains text. It can be used to load a particular font by name (such as TimesRoman or Helvetica), to set the font style (such as PLAIN, BOLD, or ITALICS), and also to set the font size. The oddly named MediaTracker class is Java's answer to the patient projectionist. It is almost always used to track the progress of images being progressively loaded over the network. You will see examples of all three of these AWT classes below. The java.applet Package. The java.applet package is quite small and has just one interesting class, Applet, with a small number of interesting methods. You have already seen the getParameter() method, which accepts a String argument giving the NAME of a PARAM, and returns the VALUE of the PARAM (or null if there is no matching name). The other three Applet methods that you will use most frequently are the following:
q q q

URL getDocumentBase(); URL getCodeBase(); AppletContext getAppletContext();

You can probably guess that the first of these methods returns a URL instance representing the value of the BASE attribute of the applet's document. It is the top of the document directory tree that the applet can access on the server host. The second of these methods is similar: It returns the URL representing the value of the CODEBASE attribute given in the APPLET tag, if any. This is used when all the Java class binaries are kept in a different server directory from the HTML files. That directory would be named in the CODEBASE attribute. TIP: The URLs returned by getDocumentBase() and getCodeBase() are always valid for use in Java applets as long as they are not null.

See "The Applet Tag" section of Chapter 10, "A Java Tutorial," for a description of the HTML elements used in declaring an applet. The getAppletContext method is used to talk directly to the browser. The applet context really refers to the browser environment in which the applet is running. Once you have obtained the applet context, you can then use it to ask the browser to display a URL, for example. This is not a task that you can perform directly in Java because of security restrictions. You will see an example of this in the section entitled "A Pop-Up Document Viewer Applet" later in this chapter. The java.util and java.io Packages. These packages are the last two on our tour of the Java Class Hierarchy. The java.util package provides various utility classes, while the java.io package handles input and output to files and streams. The java.util package contains the Date object for manipulating date items, as in JScript. It also contains a series of classes that can be used to manipulate structured collections of things, including the Vector, HashTable, Dictionary, and Stack classes. One of the most useful utility classes is StringTokenizer. This class is used to solve the age-old problem of decomposing a string, such as the following: "this,is,a,comma,separated,list" into its individual components: "this" "is" "a" "comma" "separated" "list" The traditional way of solving this problem would be to search for the separator char-acter, which is the comma character (,) in this case, and keep track of the individual substrings that occurred between the separators. We would find the first comma and separate the initial string into "this" and "is, a,comma,separated,list" and then repeat the procedure until each of the individual elements has been extracted. The StringTokenizer class completely automates this tedious but extremely common parsing task. Anyone who has ever written string manipulation code that attempts to interpret a string, a series of separate items (tokens), will appreciate the StringTokenizer class. There is not much to be said about the java.io class for applet developers. One of Java's security

restrictions prohibits local file access of any kind inside an applet. While we can certainly ask the browser to open a document using the file: protocol, the applet cannot do so itself. This restriction may be weakened in some future version of Java, but at the moment Java cannot touch the local file system.

A Pop-Up Document Viewer Applet


This section analyzes and presents a pop-up document viewer applet in Java. This applet enables the user to specify the communication protocol to be used via a pop-up menu, and also permits a full document name to be entered into a text field. Once the user commits to a particular document name by pressing a button, the applet requests that the browser open that document in a new window. This applet is designed as a simple demonstration of some of the capabilities of the java.applet and java.awt packages. It also illustrates Java's variety of event handling. The code is shown in Listing 11.4. It will also be found on the CD-ROM in the file SD.java.

Listing 11.4 SD.java--Viewing a Document in a New Browser Window Using Java


/** A Java Applet to launch a document in a new window Comments for "javadoc" follow. @author Mark C. Reynolds @version 1.0 */ import java.awt.*; // 1; get AWT components import java.net.*; // 2; get URL and friends import java.applet.*; // 3; get Applet class methods public class SD extends java.applet.Applet { String whatproto = "http"; // 5; initial protocol to use String prevproto = whatproto; // 6; previous protocol used Choice ch; // 7; A pop-up menu choice TextField tf; // 8; User entered document name AppletContext ac; // 9; Ask the browser... public void init() { // 10; Init method FlowLayout fl; Button bu; Font fo; // create a new left-justified flowlayout with 10 pixels of spacing //on each side of each item fl = new FlowLayout(FlowLayout.LEFT, 10, 10); // 14 setLayout(fl); // 15; make it the current layout fo = new Font("TimesRoman", Font.PLAIN, 18); // 16; setFont(fo); // 17; make it the current font

ch = new Choice(); // 18; create a Choice instance ch.setFont(fo); // 19; make this the current font ch.addItem(whatproto); // 20; add "http" as a choice ch.addItem("gopher"); // 21; add literal "gopher" as a choice ch.addItem("ftp"); ch.addItem("file"); add(ch); // 24; add pop-up menu to flowlayout bu = new Button("Open"); // 25; create "Open" button add(bu); // 26; add button to flowlayout // create a textfield of length 70, and put the string "http://" in it tf = new TextField(whatproto + "://", 70); // 27 tf.setEditable(true); // 28; enable user to modify field add(tf); // 29; add text field to flowlayout ac = getAppletContext(); // 30; discover our context } // 31; end of init method public void start() { // 32; start method does nothing } public void stop() { // 34; stop method does nothing too } // change the text entry when user changes protocol private void modifytext() { // 36; int len = prevproto.length(); // 37; len of prev proto String cur = tf.getText(); // 38; get the current text String left = cur.substring(len); // 39; get doc name // new name = new proto + old document name tf.setText(whatproto + left); // 40; } // 41; end of modifytext() private method private void launchdoc() { // 42; ask browser to open a doc String doc = tf.getText(); // 43; get document name URL u = null; // 44; document's URL // test to insure that there is a doc name, more than just proto:// if ( doc.length() <= ( whatproto.length() + 3 ) ) return; // 45 try { // 46; execute something that might abort u = new URL(doc); // 47; convert doc name to URL } catch (MalformedURLException ue) { // 48; // if it failed then print a message indicating why System.err.println("Invalid URL: " + ue.getMessage()); // 49; return; // 50; and give up } // 51; end of try clause // ask for the document to be opened in a new window named "New Window" ac.showDocument(u, "New Window"); // 52

} // 53; end of launchdoc // event handler public boolean action(Event ev, Object arg) { // 54; if ( ev.target instanceof Choice ) { // 55; Choice event prevproto = whatproto; // 56; save prev proto whatproto = arg.toString(); // 57; get the choice modifytext(); // 58; change the text displayed return(true); // 59; indicate event handled } // 60; end of Choice event if ( ev.target instanceof Button ) { // 61; Button event // if the "Open" button was selected then... if ( arg.toString().equals("Open") ) { // 62; launchdoc(); // 63; try to launch the doc return(true); // 64; event handled } // 65; end of if statement } // 66; end of Button event return(false); // 67; did not handle event } // 68; end of action method } // 69; end of SD class

Initializing the SD Applet


The init() method for the SD (Show Document) applet begins on line 10. Its job is to construct all the graphical elements that are displayed and, in the process, to initialize various instance variables that are used in the event handling methods, modifytext() and launchdoc(). It starts out by creating a FlowLayout instance on line 14. This instance is left justified so that new elements are added starting at the left edge of each row. We also indicate that we would like at least 10 pixels between each element in a row (the second argument to the constructor), and between rows (the third argument). Line 15 makes this layout the current layout. Because an applet is actually a Panel, this now applies to the entire applet. Line 16 accesses a plain Times Roman font with 18-point type. If your system does not have this particular font, you may need to adjust this statement to choose another font name (such as Helvetica or Geneva) and perhaps another font size (such as 24 point). You can also specify the empty string "" as the first parameter to the Font constructor; this will select a default font. Line 17 makes this font the current font for the applet's panel. Now three items are put into the flow layout, beginning at line 18: a pop-up menu, a button, and a single-line text field. The pop-up menu is created on line 18. Because pop-ups have their own fonts, which may be separate from the Panel in which they reside, you must set the font of the pop-up (line 19). This pop-up presents the user with a choice of four communication protocols that will be used. These are added to the pop-up in lines 20 through 23. Note that the default item, which represents the default protocol, is the one added first. That will be the initial value of the instance variable whatproto, which is the String "http". Line 24 finally adds this pop-up to the layout.

Line 25 creates a Button whose label is "Open". This is the button that the user presses to attempt to load a new document. It is added to the layout in line 26. The third item in our layout is an editable text field, which is created in line 27. The initial String that will be displayed is "http://", obtained by concatenating the default protocol "http" with the literal delimiter "://". Line 28 makes this text field read/write, and line 29 adds it to the layout. Because this text field is quite long, it will be added in a new row below the pop-up menu and the Open button. Finally, line 30 initializes the instance variable ac to the applet's context. This is used in the launchdoc() method. Figure 11.1 shows the initial appearance of the SD applet after the init() method has been executed. Figure 11.1 The ShowDocument Applet uses AWT elements, which are very similar to HTML forms components.

Event Handling in the SD Applet


You will notice immediately that the start() and stop() methods of the SD applet do absolutely nothing. All of the activity in this applet is triggered in response to user interaction. As a result, all of our code is within the action method and none in start or stop. There is also no run method in this applet because we are not implementing any threads (the next applet we consider uses threads). There are many different ways of performing event handling in Java. For example, Java applets that desire to handle only mouse down events can override a specialized method known as mouseDown. If you were interested only in button clicks on the Open button, you could use this approach. Because we are actually interested in handling events on the pop-up menu and button clicks on Open, the SD applet uses the more general approach. If an applet overrides the action method, this indicates that it wants to handle more than one event type. The code for the action method begins on line 54. Note that this method accepts two arguments: an Event instance indicating the type of event, and an Object instance indicating where the event occurred. The target element of an Event indicates which graphical element was associated with the event. On line 55, the Java keyword instanceof is used to ask if the event was associated with a Choice item (a pop-up menu). If the result is true, the code in lines 56 through 59 is executed. This code saves the previous choice value (line 56), stores the new choice value by extracting the String version of the Object selected (line 57), and then invokes the modifytext() private method to fix up the document name being displayed. It then returns true in line 59 to indicate that this event was successfully processed.

CAUTION: All applet event-handling methods must return true to indicate that the event has been handled and false to say that it has not. Failure to do so may cause the applet

(and the browser) to become horribly confused.

To understand what is going on, consider a concrete example. Suppose that the user had typed the document name http://ftp.javasoft.com in the text field and then suddenly realized that this was not going to work because it would require the FTP protocol rather than the http protocol. The user then invokes the pop-up choice menu and selects FTP. This selection triggers the action method of the SD applet. The test on line 55 will pass; prevproto will become the string "http" and whatproto the string "ftp". The modifytext() method on line 36 is now executed. It gets the length of the prevproto string (which will be 4), and also fetches the current document string on line 38. This will be the string http://ftp.javasoft.com. It then peels off the substring that contains everything except the protocol name in line 39. The local variable left will be the string ://ftp.javasoft.com. Finally, it glues the new protocol (stored in whatproto) onto the front of this substring and pushes that string out to the text field in line 40. The text now reads, "ftp://ftp.javasoft.com". The reader is encouraged to perform this experiment and verify that the protocol part of the text field changes in lockstep with the value of the choice selected from the pop-up menu.

Opening a New Document with the SD Applet


The action method is also equipped to handle Button events. If the test on line 61 succeeds, this indicates that some button has been pressed, and the code on line 62 will be executed. Line 62 is a bit of defensive programming in which you test to make sure that it was the Open button that was pressed. In our example, this test is superfluous because we have only one button. This line compactly converts the arg argument to a String and then uses its equals method to test against the literal "Open." This test must pass in our case, so line 63 will be executed and the launchdoc() method invoked. When that method returns, the action method returns true to indicate that the button press was handled (line 64). If this event was neither a pop-up selection nor a button press, then the action method returns false on line 67. The launchdoc() method is used actually to ask the browser to open a document URL. It first gets the text of the document name in line 43. It then checks to make sure that that string is long enough on line 45. If the string is just a bare protocol, such as "file://", this test fails and the method returns at that line. The extra 3 in this test accounts for the three characters ://. We now have a string representing a URL stored in the local variable doc, say http://www. microsoft.com. We would like to convert this to a URL instance because that is what we need for the subsequent request to the browser. This is executed in the try block beginning on line 46. A try block is required whenever a method invocation might generate a Java exception. Without being too

specific, we can say that an exception results when you attempt to do something and it fails in a potentially unpleasant way. The URL constructor on line 47 is just such a statement. How did we know this? Is it necessary to remember all the functions that can generate exceptions? Fortunately, the answer is no. If you had tried to write u = new URL(doc); without enclosing it in a try block, the Java compiler would thoughtfully tell you that URL constructors can generate exceptions and that you should try to catch the MalformedURLException. We have complied with this request and enclosed the ominous statement in a try block, which always takes the following form: try { ominous statement(s) } catch (SomeException e) { do something if an exception occurs } In our case, if doc does not correspond to a valid URL for any reason, the applet receives the MalformedURLException and the code on lines 49 and 50 (within the catch clause) is executed. This code prints out a message indicating the reason for the failure on line 49, and then returns. Note that all exceptions have a getMessage() method that we have used to tell the user why the URL was malformed. A URL might be malformed because it was entered incorrectly, referred to a nonexistent server, or mentioned a document that the server did not want the user to see, among other reasons. If the URL was well formed, the catch clause will not be executed and the code will arrive at line 52. This is the critical statement that actually communicates with the browser. We use the showDocument method of the AppletContext ac to ask it to open the URL u in a new window whose name is "New Window". This method call can still fail, of course, even if the URL u is well constructed. The reader should experiment with this applet by typing in various valid and invalid URLs, hitting the Open button, and observing the results.

Troubleshooting: I modified the code for SD.java to add a Clear button, which clears out the contents of the TextField tf using setText(""). This works fine, but once Clear has been pressed, the pop-up Choice menu function no longer works. I get garbled output. Why? The modifytext() method is the workhorse that handles the event associated with changing the choice. When you clear the text field, you are wiping out the protocol part ("http" for example) of the document name. The applet does not know this, however, because it is assuming that you will only change the protocol using the Choice item. Said another way, once you have cleared the text field, the protocol part of the document name is null, but the value of the instance variable, whatproto, is still set to the last protocol used. If you are going to enable the user to change the protocol directly, then modifytext () has to become smarter. Use the following algorithm:

1. Read in the document string using tf.getText(). 2. Find the first colon character using the String method charAt(). 3. Set the local variable, len, to the length of the substring up to that colon. Continue as written in Listing 11.4.

An Image Viewer Applet


The real power of Java comes through in its capability rapidly to display multiple images, giving the appearance of true animation on a Web page. You now have enough knowledge about Java threads and also about the AWT that you can present a simple image viewer applet in Java. This applet provides the first concrete example of something that would be difficult to accomplish in JScript. This applet can also be used as a template for writing more sophisticated applets that use Java threads. The code for the image viewer is shown in Listing 11.5. This code appears in the file Simimg. java on the CD-ROM.

Listing 11.5 Simimg.java--Displaying Multiple Images Is Easy Using Java Threads


import java.applet.*; import java.awt.*; import java.net.*; public class Simimg extends Applet implements Runnable { Image imgs[]; // 6; the images themselves int imgidx = 0; // 7; image currently being displayed int nimg = 0; // 8; total number of images Thread mythread = null; // 9; animation thread public void init() { // 10; get params and images MediaTracker mt; // 11; track image loading String tmp; // 12; tmp string String imgloc; // 13; location of images URL db; // 14; Applet's document BASE imgloc = getParameter("imgloc"); // 15; locate image dir if ( imgloc == null ) return; // 16; no img dir--give up tmp = getParameter("nimg"); // 17; get # of images if ( tmp == null ) return; // 18; no images--give up nimg = Integer.parseInt(tmp); // 19; convert to int if ( nimg <= 0 ) return; // 20; invalid # images--give up imgs = new Image[nimg]; // 21; alloc array for images // create a mediatracker for the images mt = new MediaTracker(this); // 22;

db = getDocumentBase(); // 23; find Applet's doc BASE // this loop starts loading all the images for(int i = 0, j = 1; i < nimg; i++, j++) { // 24; imgs[i] = getImage(db, imgloc + j + ".gif"); // 25; // tell the MediaTracker instance to track this image as ID 0 mt.addImage(imgs[i], 0); // 26; } // 27; end of image loading loop try { mt.waitForID(0); // 28; wait for all images } catch (InterruptedException e) { nimg = 0; // 30; if it failed set # images to 0 } // 31; end of catch clause of try block } // 32; end of init method public void run() { // 33; thread's run method Thread me; // 34; current thread me = Thread.currentThread(); // 35; get cur thread me.setPriority(Thread.NORM_PRIORITY-1); // 36; decrease pri while ( imgidx < nimg ) { // 37; loop over images repaint(); // 38; draw current image try { Thread.sleep(100); // 40; wait a little while } catch (InterruptedException e) {} imgidx++; // 42; update index to next image } // 43; end of while loop } // 44; end of run method public void start() { if ( mythread == null ) { mythread = new Thread(this); mythread.start(); } } public void stop() { if ( mythread != null ) { mythread.stop(); mythread = null; } } public void paint( Graphics g ) if ( ( imgs != null ) && ( 0 <= imgs[imgidx] != null ) { // 59; g.drawImage(imgs[imgidx], 0, 0, } } { // 57; draw current image imgidx ) && ( imgidx < nimg ) && sanity check all values this); // 60; draw it!

Initializing the Simple Image Viewer


The init method for the Simimg applet performs two functions: it gets user parameters and it loads the images. This applet requires two PARAM tags to be specified, indicating where the images are to be found and how many there are. On line 15, the imgloc parameter is accessed; if it is not present, the init method returns immediately (line 16). Lines 17 through 20 get the nimg parameter, convert it to an integer, and make sure that it is a positive number. If this parameter is not present or is not a valid positive number, the init method returns. Line 21 allocates an array just large enough to hold the indicated number of images. Line 22 initializes a MediaTracker instance. This instance will be used shortly to ensure that all images are loaded before the init method completes. Line 23 uses the getDocumentBase() method from the java.applet package to discover the applet's document BASE, saving that value in the local URL variable, db. Statement 24 sets up a for loop to load all the images into the image array imgs. Note that two iteration variables, i and j, are used. This is because the imgs array is indexed from zero, but we are assuming that the names of the images will be something like IMG1.GIF, IMG2.GIF, and so forth. The i iteration variable marches through the array, while the j variable is used to build the names of the successive images. The getImage() method is used on line 25 to launch the image loading process. It takes two arguments: a URL specifying a server directory and a String giving the name of the file within that directory that is to be loaded. We are using the applet's document BASE as the first argument, and we are constructing the successive image names using the value of the imgloc parameter (with a numeric suffix) as the second argument. This particular version assumes that all the images are GIFs.

NOTE: At present, the getImage() method understands only the GIF and JPEG image formats. Other formats may be added in the future.

The getImage() method is slightly deceptive in that it does not guarantee that the image is actually gotten when the method returns. All it does is begin to load the image. This is the purpose of statement 26. We add the image being loaded to the MediaTracker instance mt, which indicates that we are subsequently going to watch the loading process, presumably to ensure that it is done. The addImage method takes two arguments: an Image instance and an integer ID. The ID is used to group images into pools. We could, for example, track the first half of the images as ID 0 and the second half as ID 1. In this way, we could display the completely loaded ID 0 images while the ID 1 images were still being loaded.

This applet takes a brute-force approach. All images are declared to have ID 0. On line 28, we actually wait for all the ID 0 images, which are, in fact, all the images, to be fully loaded. Because this method can generate an InterruptedException, it must be executed within a try block, as we have seen in the SD applet. If this exception occurs, then we set the number of images nimg to 0, ensuring that none will be displayed. The Simimg applet, unlike the SD applet, requires PARAM tags to function properly. A sample HTML file (Simimg.htm on the CD-ROM) that uses this applet is shown in Listing 11.6. Note that this particular HTML file indicates that we will load sixteen images, that they will be located in the subdirectory "images" of the document's base directory, and that they will have the prefix "T." This means that the applet will attempt to load sixteen images named images\T1.GIF, images\T2.GIF,... images\T16.GIF. It is also worth noting that this HTML implicitly assumes that all the images will fit in a drawing area that is 300x150.

Listing 11.6 Simimg.htm--HTML for the Simimg Applet


<HTML> <HEAD> <TITLE>A Simple Image Player</TITLE> </HEAD> <BODY> <HR> <APPLET CODE="Simimg.class" WIDTH=300 HEIGHT=150> <PARAM NAME="imgloc" VALUE="images\T"> <PARAM NAME="nimg" VALUE="16"> </APPLET> <HR> The <A HREF="Simimg.java">source</A>. </BODY> </HTML>

Running the Simple Image Applet


The formal structure of this applet is exactly the same as we described previously in our discussion of threads. The start() and stop() methods are each responsible for creating the "animation" thread and for stopping it, respectively. The actual work is done by the run() method and indirectly by the paint() method. The run method first discovers the identity of its own thread by invoking the static method currentThread() of the Thread class on line 35. It then lowers its own priority to be just slightly less than the default priority for threads (line 36). This makes sense if we think of threads in terms of a standard multitasking operating system. Higher-priority tasks get more of the real CPU and generally execute more frequently. The same model applies to Java threads. By declaring itself less important, it is implicitly declaring that the drawing activity is more important.

Line 37 is the main image loop. As long as the instance variable imgidx is less than the total number of images nimg, the loop will continue. Each pass through the loop issues a call to repaint (), which results in the paint() method being executed (line 38). Each pass through the loop also puts the animation thread to sleep for 100 microseconds (line 40). This is another way to give the drawing activity even more time and also to ensure that it is actually executed. One of the side effects of using the static sleep method of the Thread class is to ensure that other threads that are waiting to run get a chance to do so. This method can also generate an exception, which we dutifully ignore. Finally, at the end of the loop, we update imgidx to process the next image. The paint method, which begins on line 57, is a model of defensive programming. It checks to make sure that the imgs array is not null, that imgidx is neither too small nor too large, and that the actual image in the imgs array itself is not null. If all these tests pass, then it uses the drawImage method of the Graphics instance, g, to draw the image (line 60). Figure 11.2 shows the result after 16 images that depict a ladybug crawling across the screen. The reader is encouraged to experiment with this applet using his own images. Figure 11.2 Java Simplifies the task of image manipulation and animation.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Chapter 19 The ActiveX Control Pad


q

The ActiveX Control Pad r Downloading and Installing the ActiveX Control Pad r Getting Acquainted with the HTML Editor r Placing Objects into Your HTML File r Editing Scripts Using the Control Pads Script Wizard s List View s Code View r Controlling Page Layout with the HTML Layout Control s Understanding the Layout Control s Inserting the Layout Control into an HTML File s Editing the Layout r Learning by Doing s Hello Jerry s Pop-Up Help (Tooltips)

The ActiveX Control Pad


In Chapter 12, "Scripting and ActiveX," you learned how to insert ActiveX controls into your Web pages using the OBJECT and PARAM tags, but doing this by hand is nasty. First, you have to find the controls CLSID. Then, you have to type the OBJECT by hand and, worse yet, set all those properties using those PARAM tags. If you're inserting more than a few ActiveX controls in your Web page, you'll quickly become frustrated. The ActiveX Control Pad (from Microsoft, of course) makes the process a whole lot easier. It has three primary features for JScript developers, as follows:
q

The Control Pad lets you easily insert ActiveX objects into your HTML files using a graphical user interface. This means that you don't have to mess around with those <OBJECT> tags at all. Point the Control Pad at a control, fill in the property sheet, and the Control Pad inserts all the required HTML into your Web page. The Control Pad provides the Script Wizard, which lets you create event handlers by associating events with actions. You make these associations using a graphical user interface, too. That means that you can avoid as many of those <SCRIPT> tags as possible, but you might still need to write them when working on more complicated scripts.

The Control Pad lets you graphically edit Layout Controls. That means that you can take full, two-dimensional control of where objects are placed on your Web page. You can actually place and edit controls just like the form editor in Visual Basic.

TIP: The ActiveX Control Pad contains the complete VB Script reference and a complete HTML reference. It also contains a reference for all of Microsoft's ActiveX controls and the Internet Explorer Object Model. Unfortunately, it doesn't include a JScript reference. To access these references, choose Help from the Control Pad's main menu. Choose either VB Script Reference, HTML Reference, or Control Pad Help Topics.

Downloading and Installing the ActiveX Control Pad


Before you can take advantage of all this wonderment, you need to download the ActiveX Control Pad onto your computer. It's a free download available through the Microsoft's Site Builder Workshop at http://www.microsoft.com/workshop/author/cpad/download-f.htm. Click Download (in the middle of the Web page) to download the self-extracting, self-installing file that contains the ActiveX Control Pad, SETUPPAD.EXE, into a temporary directory on your hard drive. Then run SETUPPAD.EXE and follow the instructions you see on the screen. After you've installed the Control Pad, you need to set it up to use JScript. Run the Control Pad. Then, choose Tools, Options, Script from the main menu. Select JavaScript, and click OK to save your changes. The Script Wizard (described later in this chapter) will now generate JScript language scripts instead of VBScript language scripts.

Getting Acquainted with the HTML Editor


Figure 19.1 shows you the Control Pad's HTML editor with an HTML file in it. You can open many HTML files in Control Pad because it's an MDI (Multiple Document Interface) application. You switch between each open HTML file using the Window menu. Figure 19.1 The Editor window shows you only the contents of your HTML. Open the HTML file in your Web browser to preview what the Web page looks like. The HTML file you see in Figure 19.2 contains an object. You see an <OBJECT> tag. You also see the object icon in the margin of the Editor window. Click this icon to change the object next to it in the Editor window. Just below the object, you see a script. You can also see the script icon in the

margin of the Editor window. You can edit the script using the Script Wizard by clicking this button. You can type any text you like in the Editor window. You can add forms to the file, for example. You can also add everyday text and tags such as headings, lists, and so on. If you're really into punishment, you can add objects to your HTML by typing them in the Editor window. Considering the features you learn in the next section, however, I strongly discourage you from doing that.

Placing Objects into Your HTML File


Inserting an object into an HTML file is easy. Position your mouse pointer to the point at which you want to insert an object, and right-click. Choose Insert ActiveX Control, and you'll see a dialog box similar to the one shown in Figure 19.2. The Insert ActiveX Control dialog box lets you pick one of the many controls that are available on your computer. Figure 19.2 The usable ActiveX controls are called things like Microsoft ActiveX something or Forms 2.0 Something. Don't use the objects whose names end with Ctl. Select one of the controls, such as the Label Object, and click OK. The Control Pad opens up the Object Editor and property sheet for the control, as shown in Figure 19.3. You can change each of the control's properties using the property sheet shown in the figure. You can also adjust the size of the control by grabbing one of its handles in the Object Editor and dragging it. Using a control in this manner is called using it at design time. You're designing how the control is going to look on your Web page. The user uses the control at runtime, however, because all she is doing is using a page built with that control. Many controls require that you have a license to use it at design time. The controls you see in this chapter don't require a license, however, because they all come with Internet Explorer. Figure 19.3 Select a property, change it at the top of the property sheet, and click Apply to save your changes. After you've made your changes to the control's property sheet, close both windows. After you close both windows, the Control Pad inserts the <OBJECT> and <PARAM> tags into your HTML file, which match how you filled in the property sheet. You can change the properties in the HTML using the Control Pad's text editor. The next time you open that control's property sheet, the property sheet will reflect any changes you made.

TIP: The Control Pad has its own way to format the <OBJECT> and <PARAM> tags. You might as well make all of your tags consistent with the way the Control Pad formats them, as shown in this chapter's figures, so that your scripts will be easier to read.

Editing Scripts Using the Control Pads Script Wizard


The Visual Basic and Visual C++ integrated development environments make the process of writing code as pleasant as possible. They provide text editors, graphical editors, and other tools to make managing objects much easier. If you've ever used these environments, you'll appreciate the Control Pad's features that make editing scripts easier. The Control Pad's Script Wizard helps you point and click your way to some terrific scripts. The best part about it is that you don't have to know anything about the browser's object model; a control's properties, methods, and events; or even the runtime functions the browser provides. The Script Wizard displays them for you, so that you can automatically insert statements in your scripts that use them. Point and click--literally. To call it a wizard is a bit misleading, however, because it doesn't act or quack like other wizards in Windows 95. It does give you a smooth interface for editing the events of each object in your HTML file, though. In fact, it lets you edit an object's events in two different ways, as follows:
q

The List view lets you associate an event with a list of actions. You give arguments for those actions by answering questions in the Script Wizard. The Code view is more of a traditional programming approach. You select an object's event, and edit the code in the window.

The following sections show you how to use both methods for editing event handlers in your HTML file. You can't use the Script Wizard to edit other types of scripts, though, such as support functions and subprocedures. That is, you can't use the Script Wizard to edit a function that's not an event handler. You can create event handlers that call your JScript functions, however.

TIP: Are you unsure which properties, methods, and events a particular object in your HTML file supports? Click the Script Wizard button in the toolbar, and select that object in the left pane to see its events. Select that object in the right pane to see its properties and methods.

List View
The Script Wizard's List view lets you edit an event handler with the greatest of ease. Click the Script Wizard button in the toolbar to open the Script Wizard. Then click the List View button at the bottom of the window. You see the window shown in Figure 19.4.

Figure 19.4 In most cases, the List view is all you ever need to create exciting Web pages. Here's how it works. You associate an object's event with another object's methods and properties by taking the following steps: 1. Expose the events for an object in the left pane by clicking the plus sign (+) next to the object. Select an event that you want to handle. You can select the window object's onLoad event, for example. 2. Expose the methods and properties for an object in the right pane by clicking the plus sign (+) next to the object. Select a method or property that you want to associate with the event you selected in the left pane. 3. Click the Insert Action button below the bottom pane. If you select a property, Control Pad prompts you for the value you want to assign to that property in the event handler. If you pick a method that has arguments, Control Pad prompts you for the arguments you want to use. If you pick a method that doesn't have arguments, Control Pad doesn't prompt you for anything at all. After you've answered any questions that Control Pad asks, it inserts the association in the bottom pane. 4. You can rearrange the order of the actions in the bottom pane by selecting an action, and clicking the up and down arrow buttons to move it around in the list. You can also remove an action by selecting it and clicking the Delete Action button. 5. When you're happy with the way you're handling that particular event, you can move onto another object and another event, or close the Script Wizard by clicking OK.

NOTE: The Control Pad creates a script block with the FOR and EVENT tags for each event that you handle. Alternatively, you can write a JScript function that handles an event the way you want, and then associate an event with the function using the Script Wizard.

Code View
If you're more comfortable with the traditional programmer view of life (optimistic about everything), you can use the Script Wizard's Code view. This works just like the List view, except that you don't see a list of associated events and actions in the bottom pane. You see the actual code the Script Wizard creates, instead. Click the Script Wizard button in the toolbar to open the Script Wizard. Then click the Code View

button at the bottom of the window. You see the window shown in Figure 19.5. You can insert actions into the bottom pane of the Code view just as you do in the List view. That is, you select an event in the left pane and select an action in the right pane. This view doesn't have an Insert Action button, however, so you double-click the action in the right pane to add it to the bottom pane. After you've added a few actions to the event handler by double-clicking them in the right pane, you can edit the code in any way you like. You can add or change the arguments for each method you use, add conditional and looping statements, or whatever you want. Figure 19.5 You have to use the Code view if you want to use compound statements such as If in your scripts. When you're happy with the way you're handling that particular event, you can move on to another event, or close the Script Wizard by clicking OK.

TIP: Keep your Web browser running with the Web page you're working on open in it. Then, you can flip to the browser and refresh the Web page to see your changes while you're working in Control Pad.

Controlling Page Layout with the HTML Layout Control


Web browsers position the content of an HTML file in a stream. That is, the Web browser reads the contents of an HTML file--left to right, top to bottom--and displays its contents in the order it encounters it. The only real control you have over the placement of an HTML file's content is through tags such as TABLE, PRE, and so on. Even these require that you understand the stream orientation of HTML. On the other hand, 2-D placement gives you complete control over the positioning of objects on a Web page. You've seen 2-D placement in many different kinds of products: Visio, Micrografx Designer, and most publishing tools give you complete placement control. You can position text so that it wraps around a graphic object in Microsoft Publisher, for example. In fact, the exception to 2D placement seems to be HTML and the Web browsers that display it. Microsoft created the ActiveX Layout Control expressly for this purpose. It gives you complete control over how you place objects on a Web page. You can place an object at a specific coordinate, for example. You can also overlap objects and make parts of some objects transparent so that objects in the background show through. The Layout Control is similar to all the other objects you've seen in this book. See Chapter 12,

"Scripting and ActiveX," for more information about using objects. You insert the Layout Control into your Web page using the OBJECT tag. It's a container, however, that can host other objects. You'll learn more about this later in this chapter.

W3C to the Rescue In the meantime, W3C (World Wide Web Consortium) is developing a standard for HTML that will give you compete control over how you position objects in a Web page. That is, you will be able to specify the exact horizontal (x) and vertical (y) positions (coordinates) of each object on a Web page. The problem is that they haven't finished their work yet, so, you need to use the Layout Control for now. You should know that the Layout Control is a temporary solution. It goes away eventually. Thus, when the W3C defines its standard and browsers such as Internet Explorer and Netscape support it, you won't need to use the Layout Control to have 2-D placement of objects. Microsoft has committed to providing a utility that you can use to convert your ActiveX Layout Control layouts to the new HTML standard for 2-D layouts when that standard becomes available. You can get more information about this standard at http://www.w3.org/pub/WWW/TR/WD-layout.html.

Understanding the Layout Control


The Layout Control is a container. This is the primary concept you need to understand about this object. It's an object you put in your Web page that can contain other objects. If you think of your Web page as a grocery bag, the controls you put in it are the groceries. With a Layout Control, you're going to put your groceries inside plastic bags (the Layout Control); then you drop the plastic bag into your grocery bag. Bet you didn't think of the Layout Control as produce, did you? Another way to think of the Layout Control is as a form. It works just like forms you create in Visual Basic or in Visual C++. You drop a Layout Control on the Web page, and then you can arrange objects within it in any way you like. You can, in fact, use the Layout Control to create virtually any form using the Visual Basic form editor. Following are some of the other things the Layout Control brings to the party:
q

You can overlap the objects you put on a Layout Control. Try that in HTML and you'll be very frustrated. You can control the Z-order of each object you overlap. That is, you can control which objects are in front and which objects are in back. You can make parts of some objects transparent so that the objects in the background show through. You can use WYSIWYG environment to place and arrange objects on a Layout Control.

NOTE: If you don't really need to control the exact location of the objects you're putting on a Web page, don't use the Layout Control. It comes with a heavy price (download time, compatibility with other browsers, and so on) that's hard to justify when you're just trying to be cute.

Inserting the Layout Control into an HTML File


A layout has two components. First, you insert the actual Layout Control in your Web page using the <OBJECT> and <PARAM> tags. This tag looks very much like this: <OBJECT CLASSID="CLSID:812AE312-8B8E-11CF-93C8-00AA00C08FDF" ID="example" STYLE="LEFT:0;TOP:0"> <PARAM NAME="ALXPATH" REF VALUE="file:example.alx"> </OBJECT> The other component is the layout itself. You store a layout in a separate text file that has the .ALX file extension. The ALXPATH property that you saw in the previous example tells the layout control where to find this file. You can set this property to any valid URL, including a Web server. You'll learn more about the contents of the ALX file later in this chapter. You don't have to insert the OBJECT tag or create the ALX file by hand, however, because the ActiveX Control Pad does it automatically. This tag simply loads an ActiveX object into your Web page that defines a region in which you can place other ActiveX objects or a layout. You don't use the insert ActiveX Object menu item; you do use the Insert HTML Layout menu item--by taking the following steps: 1. Position your mouse pointer where you want to use a Layout Control, right-click, and choose Insert HTML Layout. 2. When the Control Pad asks you for a file name, type the name of the file in which you want to store the layout, and click Open. If the file doesn't exist, Control Pad will ask you if you want to create it. As a result, the Control Pad inserts an OBJECT tag in your HTML file. Take a look at Figure 19.6--it shows what the tag looks like.

Editing the Layout


After you've inserted a Layout Control into your Web page, you can open it for editing. This allows you to place other ActiveX objects inside the Layout Control. Click the layout button (shown in Figure 19.6), and the Control Pad opens the layout in the Layout Editor, as shown in Figure 19.7.

The Layout Editor lets you drag controls from the toolbox to the layout. Then you can rearrange the controls, write event handlers for controls, and so on. Understanding What's in the ALX File. As you've seen, the Control Pad stores layouts in separate files with the .ALX file extension. It gives the name of a layout file to the Layout Control using the ALXPATH property. Figure 19.6 Insert the Layout Control using a plain old OBJECT tag. Figure 19.7 The Layout Editor is very similar to VB's Form Editor. The contents of the layout file aren't too mysterious. Each layout region begins and ends with the DIV and /DIV tags. You can give a region a name using the ID attribute, and you specify the style of the region using the STYLE attribute. Following is what the tag looks like: <DIV STYLE="LAYOUT:FIXED;WIDTH:240pt;HEIGHT:180pt;"> </DIV> What you do between the DIV tags is your business. You can insert objects into the layout by putting an OBJECT tag inside the layout's DIV tag. Inserting an object into a layout is not very different from inserting an object directly into your HTML file. The only difference is that you can specify the location of the object using the properties inherited from the Layout Control. Following is what a label control looks like in a layout file: <DIV STYLE="LAYOUT:FIXED;WIDTH:423pt;HEIGHT:265pt;"> <OBJECT ID="MyLabel" CLASSID="CLSID:978C9E23-D4B0-11CE-BF2D00AA003F40D0" STYLE="TOP:83pt;LEFT:74pt;WIDTH:72pt;HEIGHT:18pt;ZINDEX:0;"> <PARAM NAME="Caption" VALUE="MyLabel"> <PARAM NAME="Size" VALUE="2540;635"> <PARAM NAME="FontCharSet" VALUE="0"> <PARAM NAME="FontPitchAndFamily" VALUE="2"> <PARAM NAME="FontWeight" VALUE="0"> </OBJECT> </DIV> You don't need to worry about understanding or setting the DIV tag's attributes or the attributes of the objects you put in the Layout Control, though, because the Control Pad does it for you. I don't recommend editing a layout by hand anyway. It just doesn't make sense considering the tools that are available to you.

NOTE: You can also put scripts in an ALX file. You can put them before or after the

<DIV> tag, but not inside the tag, however.

Adding Controls to a Layout. Adding controls to a layout is easy. You drag a control from the toolbox and drop it on the layout in the Layout Editor. The following steps show you how to create a simple form using the Layout Editor: 1. Insert an HTML Layout Control into an HTML file and click the Layout button next to it. You'll see the Layout Editor, as shown in Figure 19.8. 2. Drag a control from the toolbar and drop it onto the layout. Change the control's ID and any other properties that make sense for how you're using the control. If the control's property sheet isn't open, you can open it quickly by double-clicking the control. This property sheet is the same one you learned about earlier in this chapter. 3. Repeat step 2 for each control you want to add to your layout. 4. Save the layout by clicking the Save button. Then, open the Web page in your browser by double-clicking the HTML file in Explorer. Figure 19.9 shows you what a layout looks like in Internet Explorer.

TIP: You can create control templates in the Layout Editor. Create a new page in the toolbox, right-click a tab, and choose New Page. Drag a control from your layout onto the new page. You can then use this template at any time by dragging it onto a layout.

Figure 19.8 You now have two files: an HTML file and an ALX file. Figure 19.9 It works! It works! Adding Scripts to Your Layout. You can add scripts to a layout just as you would add scripts to an HTML file. You use these scripts to handle the events fired by the objects in the layout. You can validate the user has entered valid text in each field, for example. Click the Script Wizard button in the Control Pad's toolbar. In this case, the Script Wizard works exactly as you learned it would in the previous chapter.

NOTE: ActiveX controls that you put on a Layout Control have many more events, properties, and methods than the ActiveX controls you use directly on the Web page. Also, when you open the Script Wizard in an HTML Layout control, you don't see the

events, properties, and methods for ActiveX controls on your Web page or the browser's object model.

Changing a Layout's Tab Order. When you create a form using the HTML Layout Control, the user can't tab between each field. That's because you haven't set up the tab behavior for each tab box. We'll deal with that nonsense here. First, double-click each control in the layout, and set the TabStop property to True and TabKeyBehavior to False (if the control supports it). Then, change the TabIndex property for each control in the layout. Set TabIndex to 0 for the first control in the tab order. Set TabIndex to 1 for the next control in the tab order, and so on.

TIP: You can leave the property sheet open all the time. When you select a different object on the layout, the property sheet changes to the one for that object.

Learning by Doing
As always, the best way to learn something like the Control Pad is to try an example. This section contains a few examples that'll help you become an expert at using Control Pad to create classy Web pages. Here are the examples you find in this section:
q

You'll re-create the example from Chapter 12, "Scripting and ActiveX," using the Control Pad. This will give you a whole new appreciation for how much trouble the Control Pad saves you. You'll learn how to add tooltips to your Web pages. That is, you'll learn how to add scripts to your Web page that pop up a little Help window when the user hovers over a link.

Hello Jerry
Remember the example in Chapter 12, "Scripting and ActiveX"? You'll create this example using the ActiveX Control Pad. In this example, the user types her name in a textbox, clicks the Display button, and receives a warm greeting from the browser. In Chapter 12, you had to insert the OBJECT and PARAM tags into the HTML file yourself--kind of a pain in the browser. Creating this Web page using the Control Pad is a snap, however, using the following steps: 1. Open the ActiveX Control Pad and create a new HTML: Click the New button, choose Internet Document (HTML) from the list, and click OK. 2. Position the cursor inside the BODY tags, and insert a Microsoft Forms 2.0 TextBox control. That is, right-click in the area inside the BODY tags, choose Insert ActiveX Control, choose Microsoft Forms 2.0 TextBox from the list, and click OK. You'll see the Control Editor, as shown in Figure 19.10.

Figure 19.10 You learned about the Control Editor in "Placing Objects into Your HTML File" earlier in this chapter. 3. In the Control Editor, select the TextBox control and stretch it by dragging the control's handles so that it's long enough to accept a user's name. In the property sheet, change the ID property of the TextBox control to txtName. Then close the Control Editor. Your HTML file should look similar to Figure 19.11. Figure 19.11 Get used to the way the Control Pad formats OBJECT and PARAM tags, because you can't change it. 4. Position the cursor inside the BODY tags again, and insert a Microsoft Forms 2.0 Command Button control. That is, right-click in the area inside the BODY tags, choose Insert ActiveX Control, choose Microsoft Forms 2.0 CommandButton from the list, and click OK. 5. In the Control Editor, select the Command Button control. In the property sheet, change the ID property to cmdDisplay and change the Caption property to Display. Then close the Control Editor. Your HTML file should look similar to Figure 19.12. Figure 19.12 The Control Pad inserts more PARAM tags than you did in Chapter 12, "Scripting and ActiveX." 6. Add a script that handles the button's Click event, displaying a message box when the user clicks it. Click the Script Wizard button in the toolbar, and change to the Code view. Select the Click event for the cmdDisplay object in the left pane, double-click the alert method for the Window object in the right pane, and change window.alert(msg) to window.alert("Hello " + txtName) in the bottom pane. Your Script Wizard window should look very similar to Figure 19.13. Click OK to save your changes.

NOTE: In the Script Wizard, the only way to see absolutely all of the methods and properties for a control is to change to the Code view. The List view hides many methods and properties of most controls.

7. Save your HTML file, and open it in Internet Explorer 3.0. Your Web page should look something like Figure 19.14. Figure 19.13 After you've edited an event using the Script Wizard's Code view, you can't go back to the List view. Figure 19.14 You can resize the Command Button Control so that it looks better beside the TextBox control.

Pop-Up Help (Tooltips)


If you're not sure what tooltips are, try this little experiment: Pop open WordPad and hold the mouse pointer over one of the buttons in the toolbar. What do you see? A little window that displays the purpose of the button. Microsoft calls these tooltips. You can use tooltips on your Web pages to provide additional help to users when they hold their mouse pointer over a link. To add tooltips, take the following steps: 1. Open the Control Pad and create a new HTML file. Add a link to the body of the HTML file. 2. Add an ID to the link using the ID attribute for anchors. That is, add ID=Name to the A tag. Figure 19.15 shows what this example looks like with a link that contains an ID of lnkHome. Figure 19.15 You can also add tooltips for images, objects, and forms. 3. Insert the Microsoft IE30 Popup Windows Control to your HTML file (if you don't have this control, see Chapter 12, "ActiveX and Script," to learn how to get it. That is, right-click above the link you added in step 2, choose Insert ActiveX Control, select Microsoft IE30 Popup Windows control from the list, and click OK. Change its ID to popTip using the control's property sheet. Change its size so that it has no height and no width. Close the Control Editor. 4. Add the following script to your HTML file. This handles the MouseMove event for the link called lnkHome. In this case, it pops up the Popup Window with the contents of LNKHOME. HTM found on my Web site. You can replace this with an HTML file on your Web site as described in the next step. <SCRIPT LANGUAGE="JavaScript" FOR="lnkHome" EVENT="MouseMove (Button, Shift, X, Y)"> <!-popTip.Popup( "http://rampages.onramp.net/~jerry/lnkHome.htm", 1 ); //--> </SCRIPT> 5. Create a file called LNKHOME.HTM that contains the formatting and text you want to display in the tooltip. You need to provide only the HTML and BODY tags, as well as the text you want to display in the Window. You can use the BODY tag's TOPMARGIN, LEFTMARGIN, BGCOLOR, and TEXT attributes to change the size of the tooltip window and its colors. Here's what the file I created looks like: <HTML> <BODY TOPMARGIN=0 LEFTMARGIN=0 BGCOLOR=YELLOW TEXT=BLACK> Click this link to go to Jerry's home page </BODY> </HTML>

6. Save your new HTML file and load it in Internet Explorer 3.0. Move the mouse pointer over the link, and you should see a small window pop up that contains the words Click this link to go to Jerry's home page as shown in Figure 19.16. When you click the mouse pointer outside the pop-up window, the pop-up window goes away. Figure 19.16 The Popup Window control only works with files using HTTP. That is, you can't use it with local files.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Chapter 5 Built-In JScript Objects


q

Built-In JScript Objects r The String Object s Chaining Methods s Anchor and Link s Listing 5.1 list5-1.js An Example Using link s charAt s indexOf s lastIndexOf s substring s Listing 5.2 An Example Using substring s Length r The Math Object s Math Methods s Math Properties s Using with and Math Objects r The Date Object s The Syntax for Creating a New Date Object s Using the Date Methods s get Methods s set s to Methods s parse Methods s JScript Examples Using the Date Object s Listing 5.3 A Simple Clock s Listing 5.4 ex53.htm--The Random Talent Generator

Built-In JScript Objects


q q q q

How to manipulate text with the String object How to use the date and time in JScript scripts How to create pseudo-random effects How to use JScript for math calculations

JScript is designed to be easy to learn and convenient to use by almost anyone who seeks to create

dynamic Web pages and client-side checking of input forms (as well as many other uses discussed in this book). Because the authors of JScript have had this in mind, they have provided you, the programmer, with many built-in objects that you will probably use quite often. These built-in objects are available through both the client-side JScript in Internet Explorer and also on the server. In addition, JScript has four objects that you can use throughout your scripts without having to declare them. The four built-in objects are: the String object, the Math object, the Date object, and the Array object. Each of these provides great functionality, and together they give JScript its power as a scripting language. These built-in objects are discussed in depth in this chapter, and you will find many examples for use in your own projects. This chapter will discuss the first three built-in objects in detail (there really isn't much to say about the Array object). Be sure to review Chapter 4, "JScript Objects," which introduced you to JScript's built-in objects.

The String Object


As you saw in Chapter 4, you can create a string object by assigning a string literal to a variable. You call a string's methods by the same dot notation you would in other objects. For example, if demostring is "Some text here!", then demostring.bold() returns "Some text here!". You can also use string methods on literals, as follows: "This is some text."italics() This line of code returns "This is some text." as displayed by your Web browser. Table 5.1 shows the various methods that you can call with the string object to alter its HTML formatting. Table 5.1 String Object Methods for HTML Formatting Method Name anchor big blink bold fixed Example "foo".anchor ("anchortext") "foo".big() "foo".blink() "foo".bold() "foo".fixed() Returned Value <A NAME="anchortext">foo </A> <BIG>foo</BIG> <BLINK>foo</BLINK> <B>foo</B> <TT>foo</TT>

fontcolor fontsize italics link small strike sub sup

"foo".fontcolor ("green") "foo".fontsize(-1) "foo".italics() "foo".link("linktext") "foo".small() "foo".strike() "foo".sub() "foo".sup()

<FONT COLOR="green">foo</FONT> <FONT SIZE="-1">foo</FONT> <I>foo</I> <A HREF="linktext">foo </A> <SMALL>foo</SMALL> <STRIKE>foo</STRIKE> <SUB>foo</SUB> <SUP>foo</SUP> uppercase UPPERCASE

toLowerCase "UPPERcase".toLowerCase () toUpperCase "UPPERcase".toUpperCase ()

Text without any modifications (denoted as Normal Text) is placed between some lines to help you see how each method changes the appearance of the text. The CD-ROM file FOO.HTM contains the source. Note that all of the strings were called as literals--that is, not as variables as you might normally see them.

Chaining Methods
Not only can you change the formatting of the text in one way at a time, you can "chain" the various methods together to mimic the behavior of nesting HTML tags around a piece of text. This can be particularly useful if you generate HTML automatically via a script. For example, the following displays a blinking "FOO" on the page: document.write("foo".toUpperCase().blink().bold()) Remember to include the parentheses after each of the methods even though they do not take any arguments. The preceding code appears to the browser as the following: <B><BLINK>FOO</BLINK></B> You can see that the <BLINK> tag is nested inside the <B> tag, because the blink method was called first. (JScript reads code from left to right and from top to bottom.) If you want to have a desired effect with nesting tags, remember that the order of nesting is the leftmost string method nested inside the next method called to the right. The reason you can nest these methods is that they all accept and return a string object, so it appears to the next method as a simple string--as if you had typed it in.

Nesting Methods versus Chaining Methods: There are usually two ways you will see methods called in scripts you encounter. You might see something like this: foo().bar().baz() "Chaining" or you might see: foo(bar(baz()))) "Nesting" The difference here can be subtle. With foo().bar().baz(), JScript will determine the result value of foo(), then treat that value as if it were the object called with .bar(). You must make sure that the value returned by the leftmost method is valid in order to have the second method "appended" to it to continue calculations. It is valid here if foo() and bar() return strings, because string literals (what each of these methods returns) can subsequently have other string methods. foo(bar(baz ())) is different in that evaluation is conducted in right-to-left order. baz() is evaluated first and then is passed as a parameter to bar(). bar() must be able to accept a parameter of this type in order for this to work. For some methods, this difference in evaluation has no effect, but for others, you might get incorrect values.

Anchor and Link


Anchors and links are often confused because they appear to create similar output. An anchor in HTML is a location for a link to point to, and is given a name for subsequent links to identify that anchor. A link is a clickable area of text or an image that jumps the browser to the anchor. See Chapter 4, "JScript Objects," for more discussion of this difference. If you want to create an anchor in JScript such as the following: <A NAME="section2">Starting Up</A> you could use: Avariable = "Starting Up" Avariable.anchor("section2") Or you can just use the following:

"Starting Up".anchor("section2") It helps to read the string like this: "Starting Up using an anchor of name section2." Links are used in a similar fashion, but in this case, instead of giving an anchor a name, you are giving a link an URL. For example, to display a link to Yahoo!, you would write the code in Listing 5.1. This code is contained in the CD-ROM file list5-1.js.

Listing 5.1 list5-1.js An Example Using link


var linktext = "Yahoo" var URL = "http://www.yahoo.com" document.open() document.write("This is a link to" + linktext.link(URL)) document.close() This is equivalent to writing the following: This is a link to <A HREF="http://www.yahoo.com">Yahoo</A> In this case, you could read the string as: "Yahoo's link is http://www.yahoo.com"

TIP: You can quickly create long strings from short ones by using the plus concatenator (+). The expression "Cat Fish" + "Sandwich" yields "Cat Fish Sandwich." Also, you can use the += operator (called the "plus-equal" concatenator) to tack a string onto the end of another. If string1 = "hello", then string1+="there" would become "hello there."

In addition to changing the formatting of a string object in HTML, you can also return parts of the string without having to know the actual contents of that string. This is extremely useful for parsing out different keywords or commands within some given input string. Table 5.2 lists the methods of the string object that pertain to displaying subsets of the string's contents. Table 5.2 String Object Methods for Displaying Subsets of Strings

Method Name charAt

Example(s) "Internet

Returned Value I Explorer".charAt(0) .charAt(10) .indexOf("net") .indexOf("e",2) .lastIndexOf("e") .lastIndexOf("e", 12) .substring(0,7) .substring(7,0) .substring(0,50) Explorer .length .substring(0,7).length

"Internet Explorer" x indexOf "Internet Explorer" 5 "Internet Explorer" 3 lastIndexOf "Internet Explorer" 15 "Internet Explorer" 6 substring "Internet Explorer" "Internet Explorer" "Internet Explorer" length "Internet Explorer" "Internet Explorer" Internet Internet Internet 17 7

Note that length is a property of a string and receives its value indirectly based on the number of characters in a string. You cannot directly assign a value to the length property.

charAt
The method charAt returns the character at the index specified. Characters are numbered from 0 to the length of the string minus 1. Its syntax is: stringName.charAt(index) For example, the following returns "n": thisstring = "Internet World" thisstring.charAt(5)

indexOf
This method can be used to search down a string (from left to right) until it finds a string fragment matching the specified value. It returns the index of the first character of the matching string. You can use this information with the method substring (mentioned later in this section) to find keywords in a given string. This is useful when you allow the user to input some information and you wish to place parts of that information into different variables. For example, the following returns 9:

thisstring = "Internet World" thisstring.indexOf("World") If the keyword is not in the string, then indexOf returns a -1.

lastIndexOf
This method is identical to indexOf except that the method searches from right to left down the string to find the given keyword. It also returns the index value of the first character of the keyword. For example, the following returns 5: "Internet World".lastIndexOf("n")

substring
substring completes the suite of subset text methods. This method returns a substring given beginning and ending index values. Note that the values do not have to be in numerical order. The string returned from substring(1,9) is identical to the one returned from substring(9,1). Also, if you leave off the second index argument, substring assumes you want it to return everything from the first index to the end of the string. And leaving off both indices returns the entire string. For example, Listing 5.2 returns "World":

Listing 5.2 An Example Using substring


thisstring = "Internet World" thewordnum = thisstring.indexOf("World") theword = thisstring.substring(thewordnum) document.open() document.write(theword) document.close()

Length
The length property appears in many types of objects across JScript, and pertains to a different value based on the context in which it is used. In strings, this value is an integer based on the number of characters in a string (counting whitespace, and so on). For a null string, this value is zero. You cannot directly alter this value except by adding or removing characters from a string. Because the value returned by "foo".length is a number, you can perform mathematical operations on it, like any other number. For instance: "Hi There".length - 1

would return the following: 7

The Math Object


As you saw in Chapter 4, "JScript Objects," the Math object provides built-in constants and methods for performing calculations within the script. The Math object's syntax is the following: Math.propertyname or: Math.methodname(parameters) Table 5.3 summarizes the various methods and properties of the Math object. Table 5.3 Math Object Methods and Properties Method Name abs acos asin cos atan ceil exp floor log max min pow random round sin sqrt tan Example Math.abs(-79) Math.acos(.5) Math.asin(1) Math.ceil(7.6) Math.cos(.4) Math.atan(.5) Math.exp(8) Math.floor(8.9) Math.log(5) Math.max(1, 700) Math.min(1, 700) Math.pow(6,2) Math.random() Math.round(.567) Math.sin(Math.PI) Math.sqrt(9801) Math.tan(1.5*Math.PI) Returned Value 79 1.047197551196597 1.570796326794896 8 0.9210609940028851 0.4636476090008060 2980.957987041728 8 1.60943791243410 700 1 36 .7877896 (varies) 1 0 99 INF (infinity) 0282 028 935 302 631 558

Math Methods
Although most of the methods used by Math are self-evident--such as using Math.sin to calculate the sine function of a number--they are summarized in the following sections, with examples for your reference. abs. abs returns the absolute value of its numeric argument. For example, the following returns 1: Math.abs(-1) acos, asin, atan, cos, sin, tan. These return that trig function in radians. The a is short for arc, as in atan = arctangent. For example, the following returns 3.141592653589793116: Math.acos(-1) ceil. This returns the smallest integer greater than or equal to the argument passed to it. This is equivalent to always rounding up to the nearest integer. For example, the following returns 15: with (Math) { foo = ceil(14.49999999); } See also floor. exp. Returns e to the power of its argument. If x is the argument, exp returns ex . (e is Euler's constant--the base of natural logarithms.) For example, the following returns 148.4131591025765999: Math.exp(5) floor. This returns the greatest integer less than or equal to the value passed to it. This is equivalent to always rounding down to the nearest integer. For example, the following returns 1: numberone = Math.floor(1.9999999); document.write(numberone); See also ceil. log. This returns the natural log of the argument passed to it. The base is e. For example, the following returns the log to the base e of pi, which is 1.144729885849400164: pie = Math.PI; pielog = Math.log(pie);

document.write("The log to the base e of PI is: " + pielog + " ."); max, min. Given two numbers, max returns the greater of the two, and min returns the lesser of the two. For example: with (Math) { document.write("Between Euler's constant and PI, " + max(E,PI) + " is greater.") } Between Euler's constant and pi, 3.141592653589793 is greater. pow. Given a base and an exponent, this returns the base to the exponent power. For example, the following returns 10000: Math.pow(10,4) random. This method returns a pseudo-random number between 0 and 1. For example, the following might return 0.09983341664682815475: Math.random() round. This method returns the argument rounded to the nearest integer. It rounds up if the fractional part of the number is .5 or greater, and down otherwise. For example, the following returns 1: with(Math) { tmp = round(1.4999999999); document.write(tmp); } sqrt. Returns the square root of its argument. Note: The argument must be non-negative; otherwise, the sqrt method returns 0. For example, the following returns 12: Math.sqrt(144); Summary of Math Object Properties Table 5.4 shows a summary of Math Object properties. Table 5.4 Math Object Properties Summary Property Name E LN10 Example (2.718281828459045091) 13.59140914229522501 Returned Value Math.E*5

(2.302585092994045901) 0.3837641821656743168 Math.LN10/6

LN2 PI

(0.69314718055994529) 3.141592653589793116

-2.025134647899099694 Math.LN2Math.E Math.sin (2*Math. PI/4)1 1/Math. SQRT2

SQRT2

0.7071067811865474617

Math Properties
The Math object provides you with a few constants that you can use for various scientific and algebraic functions. Note that these properties are constants and cannot be changed by JScript. The following is a summary with each property's approximate values.
q q q q q q q q q q q q

E Euler's constant, the base of natural algorithms. Approximately 2.718. LN2 The natural log of 2. Approximately 0.693. LN10 The natural log of 10. Approximately 2.302. PI The ratio of the circumference of a circle to its diameter. Approximately 3.1416. SQRT1_2 The square root of .5 (one half) or one over the square root of 2. Approximately 0.707. SQRT2 The square root of 2. Approximately 1.414.

Using with and Math Objects


Using the Math object is essentially identical to using other objects in JScript, with a few exceptions. If you use several Math constants and methods together in a block of code, you can use the with statement to avoid having to retype Math. over and over again. For example, the following: beta = Math.E * 62; gamma = Math.PI / 4; delta = x * Math.sin(theta); becomes: with (Math) { beta = E * 62;

gamma = PI / 4; delta = x * sin(theta); }

The Date Object


As you saw in Chapter 4, "JScript Objects," the Date object provides information about the current date and time on the client's machine. The Date object is useful for designing sites that are sensitive to the time of day or use time-based information to present new information to the user without having to use a CGI to access the server's clock.

NOTE: You cannot work with dates prior to 1/1/70. This is due to the cross-platform nature of this language--for example, UNIX machines consider 00:00:00 GMT January 1, 1970, to be "zero" on their clocks. Other operating systems have older zero settings (like Macintosh's January 1, 1904) so the most recent of them is considered the baseline for time.

The Date object is similar to the String object in that you create new instances of the object when you assign it to a variable. It differs from the String object in that you must use the new statement to create it. Using the new statement, you create a Date object that contains information down to the millisecond at that instant. Note: This data is created based on the time and date on the client's machine, not the time on the server. So, if your page is located on the East Coast, and a user visits your site from the West Coast, the time reflects your visitor's location, not yours. It is important to note this because you have no control over the time on users' machines. Their clocks may be wrong, or not even running (although this is unlikely). If your script depends heavily on having an accurate time in which to base its calculations, you might get strange effects when your script encounters these special cases. For instance, you might change the foreground text and background colors to reflect the time of day, but if the client machine's clock is off, your page will also seem "off."

The Syntax for Creating a New Date Object


To create a new Date object, you use the new operator. The Date object is predefined in JScript and will build this instance by filling in the current date and time from the client's system clock. Here is the syntax:

variableName = new Date(parameters)

For example:

today = new Date();

You have several optional parameters that you may send to the Date object, as follows:
q q

q q

variableName variableName seconds") variableName variableName seconds)

= new Date() = new Date("month, day, year hours:minutes: = new Date(year, month, day) = new Date(year, month, day, hours, minutes,

TIP: Each of these forms has a few conventions you should be aware of. The first form, in which you omit all parameters, automatically gives the current date and time in the standard format of: Day Month Date Hours:Minutes:Seconds Year For example, Sat Feb 24 14:43:13 1996 If you use the second or fourth form and omit the hours, minutes, or seconds, JScript automatically sets them to 0.

Using the Date Methods


Once you have created a Date object, you can then use the many Date methods to get or set the month, day, year, hours, minutes, or seconds of this instance. Note: You cannot set the day attribute independently--it depends on the month, year, and date attributes. As with most object methods, you simply call a Date method as follows: varibleName.methodname(parameters) For example: today.setHours(7);

There are two exceptions to this rule with the Date object: The UTC and parse methods are "static" methods, and are always called with just the generic Date object name. For example: Date.UTC(parameters) Date.parse(parameters) Table 5.5 summarizes the different Date methods. Table 5.5 Date Object Methods Method getDate getDay getHours getMinutes getMonth getSeconds getTime Example today.getDate() yesterday.getDay() today.getHours() today.getMinutes() year.getMonth() time.getSeconds() now.getTime() Returns 5 2 5 30 6 13 ***** ******

getTimeZoneoffset today.getTimeZoneoffset getYear parse setDate setHours setMinutes setMonth setSeconds setTime setYear toGMTString toLocaleString UTC now.getYear96 (the years since 1900) Date.parse(July 1, 1996) now.setDate(6) now.setHours(14) now.setMinutes(50) today.setMonth(7) today.setSeconds(7)

***** -

today.setTime(yesterday.getTime()) today.setYear(88) yesterday.toGMTString() today.toLocaleString() Date.UTC(96, 11,3,0,0,0) Sat, Feb 24 1996 14:28:15 GMT 2/25/96 14:28:15 -

Using all these methods' strings and numbers may look like a daunting task, but if you approach the Date object with a few concepts in mind, it makes working with this object much easier. First, all of the methods can be grouped into four categories: get, set, to, and parse. get methods simply return an integer corresponding to the attribute you requested. set methods allow you to change an existing attribute in a Date object--again by passing an integer--only this time you are sending a number instead of receiving it. to methods take the date and convert it into a string-which then allows you to use any of the string methods to further convert that string into a useful form. parse methods (parse and UTC) simply parse--or interpret--date strings. Second, Date attributes such as month, day, or hours are all zero-based numbers. That is, the first month is 0, the second 1, and so on. The same goes for days, where Sunday is 0, Monday is 1, and so on. The reason why numbering starts at 0 instead of 1 is that JScript closely mirrors Java in many respects--such as always starting an array of "things" with 0. This is a convention followed by many languages, and is considered a good programming practice. Table 5.6 lists the numeric conventions. Table 5.6 Date Object Number Conventions Date Attribute seconds, minutes hours day (0 = Sunday, 1 = Monday, and so on) date month (0 = January, 1 = February, and so on) year 0 + number of years since 1900 1 - 31 0 - 11 Numeric Range 0 - 59 0 - 23 0-6

Third, when a Date object is created, it takes the information from the browser's environment-usually right as the Web page is being loaded or sometime shortly after. In the following sections, each Date method is described with a brief example.

get Methods
These methods allow you to retrieve information from the current Date object. This information can be the seconds, minutes, hours, day of the month, day of the week, months, or years. Notice that there is a getDay method that will give you the day of the week, but you cannot set this value, because the day of the week is dependent on the month, day, and year. See Figure 5.1 for examples of the

get methods. Figure 5.1 The get methods extract information from a Date object. getDate. Given a Date object, this returns the date as an integer between 1 and 31. For example, the following returns 24: today = new Date("February 24, 1996") document.write(today.getdate()) getDay. This returns the day of the week. For example, the following returns "Today is Saturday": today = new Date("February 24, 1996") if (today.getDay == 0) {document.write("Today if (today.getDay == 1) {document.write("Today if (today.getDay == 2) {document.write("Today if (today.getDay == 3) {document.write("Today if (today.getDay == 4) {document.write("Today if (today.getDay == 5) {document.write("Today if (today.getDay == 6) {document.write("Today

is is is is is is is

Sunday")} Monday")} Tuesday")} Wednesday")} Thursday")} Friday")} Saturday")}

getHours. This gives you the number of hours since midnight. For example, if it is 4 P.M., the following returns, "It's been 16 hours since our party last night!": today = new Date(); document.write("It's been "+ today.getHours + " since our party last night!"); getMonth. Returns the month attribute of a given Date object. For example, the following returns 2 (if this month is March): now = newDate() nowmonth = now.getMonth(); document.write(nowmonth); getSeconds Returns the seconds of the given Date object. For example, the following displays a different image about 50 percent of the time the user loads this page: now = newDate(); if (now.getSeconds >30) {document.write("<img src = `randimage1. gif'>")} if (now.getSeconds <=30) {document.write("<img src = `randimage3. gif'>")}

getTime. Returns the number of milliseconds since January 1, 1970. This is useful in setting the time of another Date object. For example: thisDay = new Date("September 25, 1969"); myBirthday = new Date(); myBirthday.setTime(thisDay.getTime()); See also setTime. getTimeZoneoffset. This function gives you the difference between the local time and GMT (Greenwich Mean Time) in minutes. For example: now = new Date() timeDifference = now.getTimeZoneoffset; getYear. Returns an integer representing the year of the Twentieth Century. Add 1900 to this number to get the current year. For example: today = new Date("January 1, 1997"); thisYear = new Date(); var output = "Hi!"; if (today.getYear >= thisYear.getYear) { output +=" and Happy New Year!"}; document.write(output); If the year is 1996, this returns "Hi!" If it is 1997, it returns "Hi! and Happy New Year!."

set
These methods enable you to add or change attributes of the Date object. You can change the date, month, year, hours, minutes, and seconds of the Date object (see Figure 5.2). All of these methods require integers. Although you will probably use the get methods more often, these methods are handy when you quickly want to create a date and time--perhaps for displaying on a page with a modification date. Figure 5.2 The set methods modify information in a Date object. setDate. Sets the numeric date of a Date object. For example, the following returns 4: today = new Date("July 1, 1996") today.setDate(4); document.write (today.getDate())

setHours. This sets the hours of the given time. For example, the following sets the hours attribute ahead 3 hours: today = new Date() today.setHours=(today.getHours() + 3); setMinutes. This sets the minutes of the given time object (a number between 0 and 59). For example, the following returns the current Date object (now) with the minutes set for 45: now = new Date() now.setMinutes(45) setMonth. This sets the month integer in the given Date object. For example, the following returns today (with the month now May): today = newDate() today.setMonth(4) setSeconds. This sets the seconds of the given Date object. For example, the following returns now (with the seconds set ahead 5 seconds): now = new Date() now.setSeconds(now.getSeconds()+5) setTime. Sets the time value using an integer representing the number of seconds since January 1, 1970. For example: aDate = new Date(); aDate.setTime(4000*1000*1000*100); document.write(aDate); would return: Sat Sep 04 11:06:40 1982

TIP: Instead of using a large integer as a parameter, you could pass the return value from using getTime() on another date, such as: thisDay.setime(thatDay.getTime()) See also getTime.

setYear. This sets the year of the current date. For example, the following returns now (with the year now 1997): nowYear = new Date() nowYear.setYear(97)

to Methods
These methods convert date information into another format. You can convert a date into a string (based on some set of conventions--as explained later). Once you have converted the date into a string, it can be treated just like any other string for HTML formatting, and so on (see Figure 5.3). Note that the original Date object is not affected. These methods simply parse the Date object and return a string based on the information it has found. Figure 5.3 The Date to methods provide several different string output formats. toGMTString. This method converts the date to a string using the GMT convention. For example: today = new Date() document.write((today.toGMTString).bold()) This returns <B>Sat, 24 Feb 1996 17:55:33 GMT</B>. This is also rendered in bold text. Note that the bold method appended the <B> and the </B> to the string, and is not a default action of the toGMTString method. This illustrates how you can compact your code based on the assumption that a method returns a known type that you can then use with other methods. toLocaleString. This method converts a date to a string using the locale conventions. Locale conventions are specific to each area that will view this site--meaning that toLocaleString might return a different string in Europe from in the U.S., because in Europe, the day is presented before the month. So, 09/03/96 would mean September 3rd in the U.S., whereas in Europe it would mean March 9th. For example, if the date were September 4th, 1996, the following: thisdate.toLocaleString() would return the following string in the U.S: 09/04/96 08:06:40 In Europe, it would return: 04/09/96 08:06:40

parse Methods
parse methods take strings and convert them to a resulting Date object. These methods complement the to methods, in that they perform the converse of taking a date and converting it into a string. parse methods are handy in rapidly creating a Date object or simplifying the process of passing a new value to a setTime() method (see Figure 5.4). Figure 5.4 Examples of parse methods. parse. This method returns the number of milliseconds since January 1, 1970 00:00:00. It takes a string such as Feb 25, 1996 and is useful for setting Date objects that already exist. It is acceptable to use the IETF standard date syntax, such as Sat, 24 Feb 1996 18:15:11 GMT. It understands U.S. time zone abbreviations, but it is safer to use a time zone offset (thus the use for the getTimezoneoffset method). Note: The parse function is a static method of Date, so it is always called using Date.parse(), not with the name of the specific Date object instance. For example: netTime = new Date() timeString="Jul 10, 1908" netTime.setTime(Date.parse(timeString)); returns the current Date object netTime with the new month, day, and year. UTC. UTC stands for Universal Time Coordinated and is equivalent to GMT. This method is static for Date, and is always called via Date.UTC. It is called using the following syntax: Date.UTC(year, month, day) or: Date.UTC(year, month, day, hours, minutes, seconds) Remember that JScript is case-sensitive, so always use uppercase UTC. Also, remember that you use the same integer conventions listed in Table 5.6. For example: theDate = new Date(Date.UTC(96 , 1 , 24 , 12 , 45 , 22));

JScript Examples Using the Date Object


Now that you have survived learning all of the various methods, examples, and numerical conventions, it's time to begin doing some interesting things with your knowledge. The following

sections show two examples of JScript scripts that use the Date object in very different ways. One gives you a straightforward clock to add to your Web pages, and the other provides a different way of generating random numbers. By taking the current hours, minutes, and seconds of a user's visit to your Web page, you can generate a "pseudo-random" number. A Simple Clock in JScript. This script shown in Listing 5.3 samples the time every second, converts that information into a readable string, and displays that string in a small text box on the screen.

Listing 5.3 A Simple Clock


<HTML> <HEAD> <TITLE>JScript Clock</TITLE> <script Language="JScript"> <!-- Hide me from other browsers // This code was adapted from Netscape's clock, given in // their JScript examples page // Global variables var timerID = null; var timerRunning = false; // stop the clock function stopclock (){ if(timerRunning) clearTimeout(timerID); timerRunning = false; } // start the clock function startclock () { // Make sure the clock is stopped stopclock(); showtime(); } // actually display the time function showtime () { var now = new Date(); var hours = now.getHours(); var minutes = now.getMinutes(); var seconds = now.getSeconds() var timeValue = "" + ((hours >12) ? hours -12 :hours)

timeValue += ((minutes < 10) ? ":0" : ":") + minutes timeValue += ((seconds < 10) ? ":0" : ":") + seconds timeValue += (hours >= 12) ? " P.M." : " A.M." document.clock.face.value = timeValue; // you could replace the above with this // and have a clock on the status bar: // window.status = timeValue; timerID = setTimeout("showtime()",1000); timerRunning = true; } </script> </HEAD> <BODY bgcolor="#ffffff" text="#000000" link="#0000ff" alink="#008000" vlink="800080" onLoad="startclock()"> <form name="clock" onSubmit="0"> <div align=right> <input type="text" name="face" size=12 value=""> </div> </form> <H1>Now you can add a clock to your pages!</H1> </BODY> </HTML> Figure 5.5 shows how this would appear on your page. Figure 5.5 The Date object can be used to construct a simple Web page clock. The heart of this script is the function showtime(). This function creates a Date object called now and pulls out (via getHours, getMinutes, and getSeconds) the hour, minutes, and seconds values. It then creates a variable called timeValue and assigns the hour to it as a string. timeValue is interpreted by JScript as a string even though hours is a number because the first value assigned to timeValue was the empty string (""). Notice that if the hours value is greater than 12, it is reduced by 12 to account for conventional 12-hour time notation. Notice also that if the number of seconds or minutes is less than 10, the function appends a "0" before that number to keep the number of digits the same, and to avoid confusion between 03 and 30. This script runs the function showtime() every 1000 milliseconds (once a second) to display the current time in a format that is easy for the user to interpret. One of the most useful aspects of JScript is that it uses an object-oriented approach to programming. What this means is that you (the scripter) can easily take functions that you worked so hard to perfect in one script and adapt them quickly to another script--often with few or no modifications. As the comments of Listing 5.3 indicate, you can direct the output of the function showtime() to the status bar on the bottom of your browser instead of displaying it in the text box field on the page. You would do this by commenting out or deleting the following line: document.clock.face.

value = timeValue; You would also need to remove the comments (the // ) from the following line: // window.status = timeValue; It would then look like this: window.status = timeValue; Using the status line has the advantage in that the text is less likely to flicker when it updates, as many rapidly updated form fields tend to do. Also, you can easily modify this code--instead of displaying the current time on the screen--to send it to another function. This function might then use that changing information to reload a clockface image (or almost anything your imagination comes up with). Pseudo-Random Generator. Listing 5.4 shows how you can simulate a seemingly random event. The background behind this script is this: I wanted to find a way to generate a short three-word sentence based on a list of verbs, adjectives, and objects. These words came together to create a "Magic Talent," which simulates what happens to a number of fictional characters in various fantasy novel series. As someone enters the page, the date is sampled and used as a "seed" number to select one word from each list. These words are then concatenated together on-the-fly and displayed on the page. Essentially, it takes advantage of the fact that someone is unlikely to visit the page at exactly the same hour, minute, and second each day, so it appears to the page visitor that the selection is truly "random." The illusion disappears, though, if they repeatedly reload this page--since the sentence will change only slightly. This script will also be found on the CD-ROM, in the file ex53.htm.

Listing 5.4 ex53.htm--The Random Talent Generator


<HTML> <HEAD> <TITLE>Random Talents Generator</TITLE> </BODY> </HEAD> <BODY bgcolor=#ffffff> <script language="JScript"> <!-- Random Talent Generator var currentdate=0 var spacer= " " var talent= " " var theverb= " " var theadj = " " var theobjec = " " var core = 0 var description = "Here is your randomly generated

Random talent. <br> Reload after a while for a new one. <br>" function StringArray (n) { this.length = n; for (var i = 1; i <= n; i++) { this[i] = `' } return this } verb = new StringArray(10) verb[0] = `grow' verb[1] = `banish' verb[2] = `transform' verb[3] = `lift' verb[4] = `control' verb[5] = `shrink' verb[6] = `enlarge' verb[7] = `age' verb[8] = `youthen' verb[9] = `speak to' adj = new StringArray(10) adj[0] = `large' adj[1] = `small' adj[2] = `green' adj[3] = `invisible' adj[4] = `mirage' adj[5] = `glowing' adj[6] = `wooden' adj[7] = `armored' adj[7] = `imaginary' adj[8] = `glass' adj[9] = `ghostly' objec = new StringArray(10) objec[0] = `dragons' objec[1] = `animals' objec[2] = `plants' objec[3] = `fruit' objec[4] = `humans' objec[5] = `centaurs' objec[6] = `swords' objec[7] = `castles' objec[8] = `trees'

objec[9] = `pies' function getVerb (){ currentdate = new Date() core = currentdate.getSeconds() adcore = Math.floor(core/6) core=adcore theverb = verb[core] return (theverb) } function getAdj (){ currentdate = new Date() core = currentdate.getMinutes() adcore = Math.floor(core/6) core=adcore theadj = adj[core] return (theadj) } function getObjec (){ currentdate = new Date() core1 = currentdate.getSeconds() core2 = currentdate.getMinutes() core3 = core1 + core2 adcore = Math.floor(core3/12) core = adcore theobjec = objec[core] return (theobjec) } // main program document.write("Random Talent Generator".fontsize(6) + "<p>") document.write(description + spacer + "<p>" + getVerb() + spacer + getAdj()+ spacer + getObjec()) document.write("<p>") // --> </script> <p> If you do not see anything above this line, you do not have a JScript or JavaScript compatible browser.<br> </BODY> </HTML>

Figure 5.6 illustrates how this page would appear. Figure 5.6 The JScript "Random Talent Generator" uses the date as a random seed. When the user loads this page, the script creates three string arrays (verb, adj, and objec) and fills them in with the strings provided. It then uses the getVerb(), getAdj(), and getObjec() to get one of the strings in the array based on the number of seconds, minutes, or the average of the two. This is done by taking the number of seconds in the currentdate.getSeconds, dividing it by 6, and then using the Math.floor method to return an integer between 0 and 9. Because there is no real way to know when someone will visit this page, and the seconds change rapidly, there is a good chance that it will be difficult for someone visiting only once or twice a day to discern that the "Talents" aren't actually random. You also see an example of using the string method fontsize(). The method fontsize() enables you to replace the "<FONT SIZE=''>...</FONT> tags with just a number passed to the fontsize() method. Usually, this will be a negative or positive 1, to decrease or increase the font size by one point. Note that it works fine with the string literal "Magic Talent Generator". We could just as easily have assigned that string to a variable, say titleString, and then used titleString. fontsize(6).

TIP: You may find yourself using many of the same functions over and over in many different scripts. It's good practice to keep a personal library of useful functions so you can find them (and use them!) again.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Chapter 7 Advanced HTML Objects and Navigation


q

Advanced HTML Objects and Navigation r HTML Navigation Elements r Link In with JScript s Additions to the LINK Syntax s Properties of the LINK Object s The NAME Attribute Has New Significance s LINK Events: onMouseOver and onClick s Change Link URLs, Not the Text Displayed s Create Documents in Frames and Windows r Creating and Using Anchors s Your HTML Elements s Anchor Any Text or Element r Using Selection or Scrolling--Your Option s Syntax in Review s onChange, onBlur, and onFocus Events for SELECT s Dynamically Change the Selection, Not the Text r Example: An Application Using Advanced Navigation s Expand the View with Frames s Anchors to Complete the Story r Example: Tri-Eye FTP Auto Dialer s Other Possible Improvements to and Uses of Internet Tri-Eye

Advanced HTML Objects and Navigation


q q q q

Change the hyperlinks Learn the importance of the NAME attribute Select input verification Build a browser within a browser

HTML Navigation Elements


Your users will demand quicker response time as you add more interactivity. Before JScript, most interactive features required your Web page to invoke a CGI script on the server. The more interactivity, the more the users have to wait for the server to deliver new documents. The response

time improves dramatically as JScript handles interactivity on the browser side instead of waiting for CGI scripts. To meet this increasing demand for better response time, you will increase the size of your Web documents with JScript. This is because your pages are more like applications and less like plain reading material. As your document gets larger, you will incorporate more navigational aids. You will create dynamic elements with JScript to let users quickly see the material they want and skip irrelevant information. And you will do this without waiting for the server. Controlling the flow of user interaction is critical to good design. You can confuse your users with the multiple windows and frames possible in the new browsers. The dynamic capability of JScript allows you to create new documents in response to your users' preferences. For example, if the viewer selects a favorite sport, the hyperlink named "Last Year's Champion" could vary based on the viewer's selection. With JScript's features, you can transform the browser from static displays to interactive applications. There are a variety of examples in this chapter that let you try out the new dynamics of hyperlinks, anchors, and selection lists. The chapter concludes with a much larger application that shows you the possibilities of JScript.

Link In with JScript


Click and follow the designer's lead. That's how people navigate the Web: They follow the links chosen by the designer. Click the same link a hundred times, and it takes you to the same page every time. Every user is different and has different expectations. For example, a link that's appropriate for an adult might be too complex for a young child. This limitation of HTML drives many people to try to "build a better Web page." You probably looked at a few poorly designed Web pages and were frustrated by the hyperlinks designed into those pages. As a designer, you might have chosen other sites to link to. So, people build other Web pages and try to make them perfect for their audiences. They still end up with pages in which the viewer follows the designer. Your links are now dynamic with JScript. Based on options a user can select, clicking the link takes the user to different places without waiting for a CGI script to feed a page from the server. Also, by using the frames and windows, your existing page is not necessarily replaced by the new page. Your browser can be a kaleidoscope on the Web, simultaneously viewing multiple sites around the world. Or you can pull in different publications based on the day of the week.

Additions to the LINK Syntax


You are probably familiar with using the link tag in an HTML document. A very simple example is the following:

<A HREF="http://www.yoursite.com">Click here</A> Your browser would display "Click here" as a hyperlink. The reference of a LINK is an URL or a location. You know the World Wide Web protocol, which is http:// as you see in the preceding example. You could also have used the MailTo protocol (for example, mailto:info@mailcall.com). There are formats for FTP, Gopher, and File. A new URL type is now defined for JScript. The protocol is simply javascript::. For example, you could specify JScript: history.go(-1) as the URL. When used as the URL for a LINK, the browser executes the statement following the colon. In the following example, it executes: history.go(-1). As a useful example, try adding the following line to any page: <A HREF="JScript: history.go(-1)>Go back to previous page</A> This is particularly useful on documents displayed in browser windows where you have disabled the toolbar. When you click this hyperlink, the browser takes you back to the previous page in your history list. If you want to test this, open your browser and load your default home page. Then load the page in Listing 7.1 called history.htm on the CD-ROM. Clicking the hyperlink returns you to your default home page.

Listing 7.1 history.htm--Demo of JScript URL


<HTML><HEAD><TITLE>history.htm by Ray Daly</TITLE> </HEAD><BODY> <P>Juno said, "<A HREF="javascript:history.go(-1)"> History will repeat itself.</A>"<P> </BODY></HTML> The limitation on the javascript: protocol is that it evaluates its expression to a location. In other words, the result of the expression should be a string that represents a location. For example, earlier in your code you could set a variable equal to an URL. Then, use the javascript: protocol in a link to jump to that location: Var demoloc="http://www.microsoft.com" <A HREF="javascript:demoloc">

NOTE: Internet Explorer does not currently support the about: protocol. Therefore, URLs such as "about:plug-ins" will not work at present.

Properties of the LINK Object


Each object has properties. The properties of the LINK object tell you about the URL. There is also a property to tell you the target for the document. Listing 7.2 shows a small page that gives all of the LINK properties in action. When this page is loaded into Internet Explorer, Figure 7.1 results. Figure 7.1 All of the properties, except TARGET, extract substrings from the HREF property.

Listing 7.2 linkprop.htm--Demo of LINK Object Properties


<HTML><HEAD><TITLE>linkprop.htm by Ray Daly</TITLE></HEAD><BODY><P> <B>LINK[0]: </B> <A HREF="http://www.yoursite.com:80/mystuff/index.html? search=htmljive" TARGET="parent.bottom"> http://www.yoursite.com:80/mystuff/index.html:80?search=htmljive</A> <BR><B>LINK[1]: </B> <A HREF="http://www.yoursite.com:80/mystuff/index.html#anchorhere" TARGET="parent.bottom"> http://www.yoursite.com:80/mystuff/index.html:80#anchorhere</A> <BR><BR>>This demonstrates the properties of the LINK[0] object. <SCRIPT LANGUAGE="JavaScript"> document.write( "<BR>hash = " + document.links[0].hash) document.write( "<BR>host = " + document.links[0].host) document.write( "<BR>hostname = " + document.links[0].hostname) document.write( "<BR>href = " + document.links[0].href) document.write( "<BR>pathname = " + document.links[0].pathname) document.write( "<BR>port = " + document.links[0].port) document.write( "<BR>protocol = " + document.links[0].protocol) document.write( "<BR>search = " + document.links[0].search) document.write( "<BR>target = " + document.links[0].target) document.write( "<P>>The LINK[0] has no hash. ") document.write("However the LINK[1] has:<BR>") document.write( "hash = " + document.links[1].hash) document.write("<BR><BR>The number of links = ") document.write( document.links.length) </SCRIPT></BODY></HTML>

The NAME Attribute Has New Significance


Prior to putting JScript into HTML pages, there was not much point in using the NAME attribute, so many tags remained nameless. NAME was used only for anchors and when sending form information

to a CGI script. As you use JScript to make your links dynamic, you need to distinguish between the various links on your page. The properties of the link object are accessible using the following format: document.links[index].propertyname But in using this format, you need to know the index number. The index number is assigned to each LINK object in sequence as it is loaded by the browser. The first link loaded has the index of 0, the second is 1, and so on. So, you need to keep track of the order the LINK objects are loaded. This is the default method of accessing properties. Often, a simpler means is to name the elements that are referenced by your JScript code. Therefore, using our first example, add the NAME attribute as follows: <A NAME="myname" HREF="http://www.yoursite.com">Click here</A> Now your JScript code can access the properties of this object without having to know the index number. Simply use the following format: document.name.propertyName Using the NAME attribute is probably familiar to you if you have used anchors in your HTML documents. It is the identical format and is still how you create anchors. So, whenever you use the NAME attribute for your JScript code, you are also adding a new Anchor.

LINK Events: onMouseOver and onClick


JScript code executes when the browser recognizes certain events. The link object recognizes two events: onClick and onMouseOver. You will probably use onClick in most of your code and onMouseOver only occasionally. This will remind you of the format of these events used with the LINK tag. See Chapter 3, "Events and JScript."

TIP: In debugging code involving the status bar, make sure you include the statement, return true.

The format is the same as for other events. Use our example, as follows: <A NAME="myname" HREF="http://www.yoursite.com"

onMouseOver="window.status='Please visit my site.'; return true"> Click here</A> This places the message Please visit my site. in the status bar when the viewer places the mouse pointer over the hyperlink. This overrides most browsers that would display the URL in the status bar in this event. You can use this feature to change the look and feel of your pages. Instead of showing the URL, which is irrelevant to many, change your links to tell people verbally where the links will take them. So, instead of displaying something like: http://www.cris.com/~raydaly/sponsors.html you can display an easier-to-understand message in the status bar, such as:

Hyperlink to "Sponsor of the Day" The onClick event uses the same format. Also, the example application for this chapter makes frequent use of the onClick event. The following is a short example: <A NAME="mymessage" HREF="http://www.newsite.com" onClick="alert(`Thanks for visiting. Enjoy the new site.')"> Visit Newsite</A> This code displays an Alert dialog box prior to jumping to the new site (see Figure 7.2). Only after the user clicks OK in the dialog box does the browser hyperlink to www.newsite.com. Figure 7.2 You can display a dialog box prior to hyperlinking to a new site.

CAUTION: You can confuse your users by changing the HREF using onClick. Users often look to the status bar to see the URL that the hyperlink will take them to. When you assign the HREF attribute of the LINK, it is displayed in the status bar. When using the onClick event, you can set the HREF to a different URL. By reading the status bar, the user may assume he or she is going to the first URL, but instead, your JScript code takes him or her to the URL specified by the onClick statement. In the following example, the status bar makes it appear that the link is to Yahoo!'s site, but the code takes you to InfoSeek. It goes to show that you cannot even trust links anymore. <A NAME="searchme" HREF="http://www.yahoo.com" onClick="this.href='http://www.infoseek.com'"> Search Internet for a Topic</A>

To avoid such a discrepancy in the status bar, just add onMouseOver to change the contents of the status bar. For the preceding example, just insert the following as the second line: onMouseOver="window.status='Will take you to a search engine.'; return true"

Change Link URLs, Not the Text Displayed


Unlike text boxes, JScript cannot change the hyperlink text displayed by the browser. In Listing 7.3, the hyperlink text is Yahoo!. Regardless of the changes you make to this object, this stays on the screen. As you design your dynamic links, consider the words and images that reflect the new nature of your hyperlinks. For example, you could write a simple random URL function. When you click the link, it takes you to a random search site. You might use the words, Spin the wheel to a random search site, or add a graphic image of a roulette wheel. Listing 7.3 is an example showing how to make a dynamic link to Yahoo!. The browser simply displays the hyperlink text Yahoo!. When you click this link before 6:00 P.M., you link to the textonly version of Yahoo! But after 6:00 P.M., you link to the regular graphic version of Yahoo!. So the HREF changes, but the displayed text stays the same. This code will be found in the CD-ROM file atlyahoo.htm.

Listing 7.3 atlyahoo.htm--Page with Alternative Yahoo! Links


<HTML> <HEAD><SCRIPT Language="JScript"> function timeText () { today=new Date() hour = today.getHours() //...get hour of the date if (hour>18 ) { //...after 6:00 p.m use graphics yahooURL= "http://www.yahoo.com/" } else { //...all other times use test mode yahooURL = "http://www.yahoo.com/text/" } return yahooURL //...result of function is an URL } </SCRIPT></HEAD> <BODY>

<A NAME="yahooLink" HREF="" onClick="location.href=timeText()" //...get the right URL onMouseOver="window.status='Hyperlink to Yahoo!'; return true"> Yahoo!</A> </BODY></HTML> The URLs are not just for the Web. For example, suppose you have a fairly lengthy form to be completed by a customer, and one of the first entries asks about the customer's location. Based on that entry, you might dynamically change the mailto address. Then, any e-mail the customer might send is directed to the proper salesperson. Listing 7.4 asks the user where he is located. (This code is included on the CD-ROM as atlmail2.htm.) Based on his selection, e-mail goes to a different address. Figure 7.3 shows the result of Listing 7.4.

Listing 7.4 atlmail2.htm--Page that Switches Mailto Addresses


<HTML> <HEAD> <SCRIPT Language="JScript"> var salespersonMailto; </SCRIPT> </HEAD> <BODY> <FORM> <B>Where are you located?</B><BR> <INPUT TYPE="radio" NAME="country" onClick="salespersonMailto= `mailto:worldsales@company.com'"> Outside North America<BR> <INPUT TYPE="radio" NAME="country" onClick="salespersonMailto= `mailto:nasales@company.com'"> North America<BR> </FORM> <A NAME="salesperson" HREF="mailto:info@yoursite.com" onClick="location.href=salespersonMailto"> Email your salesperson.</A> </BODY></HTML> Figure 7.3 Depending on the selection, e-mail goes to a different address. Remember to include a default address or use a dialog box to ask the user to make a choice before trying to send e-mail.

Create Documents in Frames and Windows


The LINK tag now enables the designer to specify the TARGET for the URL. This is an optional attribute. If it is not used, the new page simply replaces the previous page as before. But JScript allows you to display these new pages in frames or new windows. One target for your link can be a new browser window. The windows will generally look and

function as if you opened a second browser. Therefore, the original page is still displayed in your first window, and the new page is displayed in the second. You can reduce the functionality of these windows by changing their features when the windows are open. A frame is the other possible target for your link. Frames divide your browser window into two or more areas. Inside these frames, you can display standard Web pages or create your own documents. The applications constructed in this chapter use frames. A review of frames will be found in Chapter 19, "The ActiveX Control Pad." Windows and frames are often a vital part of a design with dynamic links. Using JScript code behind a link, you can build new types of browsers. You can also build new tools. For example, you might bring a page into a frame, analyze it, and display the results in another frame. Often, when using frames, one area is like a control panel that can control the display in another. For example, researchers constantly use different search engines on the Web, and these sites are bookmarked. But it would be handier if these sites were always available like the toolbar buttons in Internet Explorer. Listings 7.5, 7.6, and 7.7, called SearchDr, show how the top frame contains one line with hyperlinks to eight different search engines. This frame is like a control panel with the documents targeted at the lower frame. Figure 7.4 shows the result. These listings will be found on the CD-ROM in the files searchdr.htm, display7.htm, and searc".htm.

Listing 7.5 searchdr.htm--Top Page for SearchDr


<HTML><HEAD><TITLE> searchdr.htm </TITLE></HEAD> <FRAMESET ROWS="60,*"> <FRAME SRC="searc".htm" NAME="buttons"> <FRAME SRC="display7.htm" NAME="display"> </FRAMESET> </HTML>

Listing 7.6 display7.htm--Initial Screen in Display Frame


<HTML><HEAD><TITLE>Part of searchdr.htm: display7.htm</TITLE></HEAD> <BODY><H1>Display Area</H1> <P>Click on any hyperlink above to display a search engine here. </BODY></HTML>

Listing 7.7 searc.htm--Frame for SearchDr with Hyperlinks


<HTML><HEAD><TITLE>Part of searchdr.htm: searc".htm</TITLE></HEAD> <BODY> <A HREF="http://www.altavista.digital.com/" TARGET="display"> Alta Vista</A> -<A HREF="http://www.excite.com" TARGET="display">Excite</A> --

<A HREF="http://www.lycos.com/" TARGET="display">Lycos</A> -<A HREF="http://www.mckinley.com/" TARGET="display">Magellan</A> -<A HREF="http://www.nlightn.com/" TARGET="display">NlightN</A> -<A HREF="http://www.opentext.com:8080/" TARGET="display">Open Text</ A> -<A HREF="http://www.webcrawler.com" TARGET="display">WebCrawler</A> -<A HREF="http://www.yahoo.com" TARGET="display">Yahoo!</A> </BODY> </HTML> For a more substantial example, we will construct an application in this chapter called Internet TriEye. It will truly give you a different view of the world. In Listing 7.8 and its corresponding Figure 7.5, you see the frames used in creating Internet Tri-Eye. This code is contained in the CD-ROM file trieye.htm. Although this will be displayed using your browser, it is not the same old browser anymore. Frames and dynamic hyperlinks let you reshape the browser. Figure 7.4 SearchDr puts any of the listed search engines in the frame marked Display. When you create frames, let the default frames provide instructions to the new users.

Listing 7.8 trieye.htm--Frame Document for Internet Tri-Eye


<HTML><HEAD><TITLE>Internet Tri-Eye</TITLE></HEAD> <FRAMESET ROWS="*,200"> <FRAMESET COLS="33%,34%, 33%"> <FRAME SRC="one.htm" NAME="one"> <FRAME SRC="two.htm" NAME="two"> <FRAME SRC="three.htm" NAME="three"> </FRAMESET> <FRAME SRC="guide.htm" NAME="guide"> <NOFRAMES> <H1>Internet Tri-Eye</H1> <P><B>Internet Tri-Eye</B> is a demonstration of several features of JScript. To view and use this program you need a JScript or Javascript compatible browser. </NOFRAMES> </FRAMESET></HTML> Figure 7.5 The frames used to create Internet Tri-Eye will contain the control panel at the bottom and display

Internet camera pictures from around the world.

Creating and Using Anchors


Anchors are not commonly used on most Web pages. If you have an alphabetical listing, an anchor might take you to a particular section. However, most sites have tended to use rather short pages. These pages might be one or two screens in length and often do not need anchors.

Your HTML Elements


The pages you design with JScript are fundamentally different from most other HTML pages. Because they are so interactive, your viewers will spend more time on your pages than on the average HTML page. They may also save the page, because it is not just a page of text anymore, but an application. These differences should make you consider making your pages bigger than before. The user may be willing to wait a little longer for a page to load if that means it will be richer. Because your pages are now applications, users will expect quick responses to their inputs; you cannot deliver that promise if you have to keep requesting documents from the server. Instead, take what you might have normally put on several different pages and build it into one big page. This can also benefit users because when they save the page, they can have the complete application. For example, with your Great JScript Application, you might have a page of help and documentation. Given the sophistication of your application, this could be fairly lengthy, and normally you might consider separating it from the application page. However, if you follow that course, when users save the application, they will not have the help when loading it from their hard drives. Instead, consider making a bigger page that includes all of the help information and documentation. Then, set up anchors to the help topics so people can easily refer to them. This concept is illustrated in Figure 7.6. Figure 7.6 By combining multiple pages into one, your JScript application becomes more responsive. The fewer the requests to the server, the more responsive your application will be. When you have longer documents, anchors become crucial for navigating around the document. Instead of scrolling through screen after screen, click the keyword, and you have found your place. Use this technique for documentation, help, or other reference material.

Anchor Any Text or Element


Use anchors in the standard way and in new ways with JScript. Anchors enable you to specify a destination for a hyperlink within a document. For example, suppose you want to be able to jump to the words, "Part Two." Then, you would put this code in your document:

<A NAME="jumphere">Part Two</A> Note that the name does not have to be the same as the text. In this example, the name is jumphere, and the text displayed by the browser is "Part Two." To create the hyperlink to this section, use the following code: <A HREF="#jumphere"> Go To Part Two</A> This is useful not only within the current document, but also when pulling up information within frames or in other windows. For example, take the case of a form in which you are verifying the input. You would probably use a dialog box to notify the viewer that the input is out of range; then, use an anchor at the description of the text box, and link the browser to it with hypertext. Now, the text box is right at the top of the screen, awaiting a new input.

NOTE: You can use the anchor to scroll the page to the place you want. The FOCUS and the SELECT methods can do the same with form elements. However, if your form elements have labels, these methods will move the element to the top of the screen, cutting off your label. If you want your users to be able to read the labels, anchor the labels and jump to them. Both techniques are illustrated as follows.

Anchors can also provide you a new way to control the flow in completing a form, as shown in Listing 7.9 and Figure 7.7. This code will be found on the CD-ROM in the file verfname.htm. Often, in completing paper forms, you see such instructions as If you answered NO to question 6, skip to question 9. With JScript and anchors, you can look at the response to a question, then--depending on the answer--automatically jump to the anchor for the next appropriate question.

Listing 7.9 verfname.htm--Anchors in Form Verification


<HTML><HEAD><TITLE>verfname.htm by Ray Daly</TITLE> <SCRIPT LANGUAGE="JavaScript"> function skip2 (form) { if (form.q1.value>11) { alert (`You get FREE Overnite Shipping. Skip to question 12.') form.q2.value="FREE Overnight" window.location="#a12" //...jump to anchor a12 } if (form.q1.value<0) { alert (`You cannot return these items') form.q1.value="" form.q1.focus()

form.q1.select() //...instead of jumping to an anchor, this uses focus and select method } } </SCRIPT></HEAD><BODY><FORM> <P>Try filling in quantities of 16, 8 and -3. </P> <B>1.) How many do you want?</B><BR> FREE Overnite shipping when ordering 12 or more.<BR> <INPUT NAME="q1" TYPE="Text" onBlur="skip2(this.form)"><BR> <a NAME="a2"> <B>2.) How do you want it shipped?</B><BR> <INPUT NAME="q2" TYPE="Text" ><BR> <BR><BR><BR><BR><BR><BR> <I>(more questions are listed here) <BR><BR><BR><BR><BR><BR> <BR><BR><BR><BR><BR><BR> <B>12.) What color do you want?</B><BR> <A NAME="a12"><INPUT NAME="q12" TYPE="Text" ><BR> <BR><BR><BR><BR><BR><BR> <I>(more questions are listed here) <BR><BR><BR><BR><BR><BR> <BR><BR><BR><BR><BR><BR> </FORM> </BODY></HTML> Figure 7.7 You will see a visual difference in comparing the use of anchors to control the flow or the use of the FOCUS and SELECT methods.

TIP: In debugging your JScript, check your quotes. While double quotes and single quotes work in the same way, you cannot start with a double quote and end with a single quote, or vice versa. Your quotes must match or you will end up with errors, perhaps several lines later.

Using Selection or Scrolling--Your Option


What kind of test did you prefer in school: multiple choice or essay? You probably found multiple choice easier. Certainly, your teacher found multiple choice easier to grade. When you design interactive forms, your viewers probably also find your requests easier to

understand in a multiple choice format. Understanding this aspect of form design, you have probably used option buttons and check boxes. These are excellent devices for presenting a limited number of choices. When you present the viewer with a large number of choices, use the SELECT element. This enables you to present a large list without cluttering up your page. A good use would be geographical lists, such as states or countries in address forms.

Syntax in Review
Although using the SELECT element makes it easier for visitors to your site, you have to do more work. Remember, SELECT is an element within a form, so it must be between the <FORM>...</ FORM> tags. The syntax of SELECT is one of the most complicated of all the HTML elements. You should be familiar with most of this specification. Listing 7.10 shows the syntax for this element.

Listing 7.10 Elements of the HTML SELECT Statement


<SELECT NAME="selectName" [SIZE="integer"] [MULTIPLE] [onBlur="handlerText"] [onChange="handlerText"] [onFocus="handlerText"]> <OPTION VALUE="optionValue" [SELECTED]> textToDisplay [ ... <OPTION> textToDisplay] </SELECT> The SELECT tag has one required attribute: NAME. This name and a value associated with the selected OPTION element are sent to the server when a form is submitted. The NAME attribute can also be used as an anchor. An optional attribute is SIZE, which tells the browser how many options to display. MULTIPLE is an optional attribute of SELECT, which changes the list so that one or multiple items can be selected by the user. This type of list is called a scrolling list. The SELECT tag always contains two or more OPTION elements. This is where you list the items for the user to select. Each OPTION has a text property that is displayed in the select box. There is also an associated VALUE property that is sent to the server when the form is submitted along with the name of the SELECT tag. The last attribute of OPTION is itself optional. The SELECTED attribute is a means to have one of the items in your selection list be the default when the page is displayed. The only addition to this specification for JScript is the events discussed in the next section.

onChange, onBlur, and onFocus Events for SELECT

Like other objects in JScript, the SELECT object responds to events. Here, you will learn specific uses of onFocus, onChange, and onBlur with SELECT objects. See "Events and JScript." onChange. onChange is the most common event that you monitor in SELECT. It looks for change from one selection to another. When the event is triggered, your code executes. An example of using onChange, by selecting a country, is shown in Listing 7.11 and Figure 7.8. Say you change a country selection from the United States to Mexico. Then, onChange triggers a JScript function that changes the currency type from U.S. dollars to pesos. However, if you did not change the selection, the event does not trigger. This file appears as money.htm on the CD-ROM.

TIP: When using SELECT, you have a built-in associate array. Each OPTION value relates to a selection.

Listing 7.11 money.htm--Currency by Country Using onChange


<HTML><HEAD><TITLE>money.htm by Ray Daly</TITLE> <SCRIPT LANGUAGE="JScript"> function changeCurrency(form) { form.currency.value=form.country.options[form.country. selectedIndex].value } </SCRIPT></HEAD> <BODY><FORM> <P>This page demonstrates the <I>onChange</I> event.</P> <B>Select your country</B><BR> <SELECT NAME="country" onChange="changeCurrency(this.form)"> <OPTION VALUE="US Dollars">USA <OPTION VALUE="Canadian Dollars">Canada <OPTION VALUE="Peso">Mexico </SELECT> <P><B>Prices are displayed in:</B><BR> <INPUT TYPE="text" NAME="currency"> </FORM></BODY> </HTML> Figure 7.8 The onChange event is triggered when the selection changes. onBlur. onBlur is a good way to verify proper selections. This event occurs when the focus is no longer on the SELECT object. In other words, it looks for when you click somewhere other than on

the current element. When the event is triggered, you could execute a verification function. Although you can use the onChange event to verify selections, using onBlur might ensure your site visitor's choice. This is because the onBlur event triggers JScript code even if a change has not occurred. Verification is not always simply an either/or choice. For example, you might have a selection with some uncommon but acceptable answers. This might be an unusual color for a piece of merchandise. For this circumstance, you might verify that this is indeed the correct selection, even if the user made no change in his or her selection. In Listing 7.12, the user is simply notified with an Alert box if he or she wants to buy fewer than a dozen eggs. The result of executing this page is shown in Figure 7.9. This script will be found on the CD-ROM in the file eggs.htm.

Listing 7.12 eggs.htm--Eggs Come by the Dozen Using onBlur


<HTML><HEAD><TITLE>eggs.htm by Ray Daly</TITLE> <SCRIPT LANGUAGE="JScript"> function checkEggs(form) { form.eggs.value=form.quantity.options[form.quantity.selectedIndex]. value if (form.quantity.selectedIndex==0) { alert (`People usually order eggs by the dozen.') } } </SCRIPT></HEAD> <BODY><FORM> <P>Demonstrates <I>onBlur</I> event. After you select a quantity, the number on-hold is not updated until you click somewhere else.</ P> <B>How many eggs do you want:</B><BR> <SELECT NAME="quantity" onBlur="checkEggs(this.form)"> <OPTION VALUE="6">Half dozen <OPTION VALUE="12">Dozen <OPTION VALUE="24">Two dozen </SELECT> <P><B>We are holding this many eggs for you:</B><BR> <INPUT TYPE="text" NAME="eggs"> </FORM></BODY> </HTML> onFocus. onFocus is an excellent way to assist your site visitor in completing your form. It looks for the visitor to move the cursor to the SELECT element and then triggers code prior to any entry by the visitor. For example, each question in your form can include particular instructions that assist the visitor in making a proper selection. When onFocus is triggered, your code could display in a separate window or frame the instructions related to that question. Or, if you require a numeric answer to be calculated, why not pop up a calculator in a new window? That's what happens in the math word problem presented in Listing 7.13. The results are shown in Figure 7.10, and the code itself can be found on the CD-ROM in the file wordprob.htm.

Figure 7.9 The event onBlur works almost exactly like onChange, except the JScript code is executed even if the selection does not change.

TIP: It is possible to create an endless loop using the onFocus event. To avoid this trap, create a flag variable. Initially set it to zero. Every time you call the routine, check the value of the flag. If the flag is zero, then execute the rest of the routine and set the flag to one. If the flag is not zero, then the routine has already been executed once, so you don't need to execute it again.

Listing 7.13 wordprob.htm--Tricky Math Word Problem Using onFocus


<HTML><HEAD><TITLE>wordprob.htm by Dr. Ray Daly III </TITLE> <SCRIPT LANGUAGE="JScript"> function giveAnswer(form) { if (form.answer.selectedIndex==2) { alert (`People usually forget trains run on two tracks.') } } already=0 function callCalculator(form) { if (already==0) { already = 1 //...only need to open this window once newWindow=window.open("http://www.netscape.com/comprod/products/ navigator/ version_2.0/script/calc.html") } } </SCRIPT></HEAD> <BODY><FORM> <P>Demonstrates <I>onFocus</I> event. As soon as you click on the SELECT element, then a calculator pops up.</P> <P><B>Railroad track is ordered for three sections of track. The first is 15 miles long. The second is 23 miles long and the third is 6 miles long. How many miles of track needs to be ordered to complete construction? </B></P> <P><B>What is your answer:</B><BR> <SELECT NAME="answer" onFocus="callCalculator(this.form)" onBlur="giveAnswer(this.form)">

<OPTION VALUE="21">21 <OPTION VALUE="29">29 <OPTION VALUE="88">88 </SELECT> </FORM></BODY> </HTML> Figure 7.10 When you design your JScript applications, remember that you can call up other people's applications.

Dynamically Change the Selection, Not the Text


Unlike its textbox cousins, TEXT and TEXTAREA, your code cannot change the text displayed in the SELECT list. Although your viewer may have chosen Canada as the country, your code cannot substitute the name of the provinces for the names of the states as the text displayed by the options. However, your code can dynamically change the selection made. The selected property reflects the selection status of an option. You can set selected, which immediately changes the selection displayed on the browser display. You can see how this works by using option buttons to change a SELECT list dynamically. Listing 7.14 illustrates how this works, with the resulting output shown in Figure 7.11. This code will be found on the CD-ROM in the file dinner.htm.

Listing 7.14 dinner.htm--Pizza for Dinner Using the SELECTED Property


<HTML><HEAD><TITLE>dinner.htm by Red Daly</TITLE></HEAD> <BODY><FORM> <P>Demonstrates <I>selected</I> property. See what you can afford for dinner. Click on the radio button for a dollar amount and show your dinner in the select box..</P> <P><B>How much money do you have for dinner?</B><BR> <INPUT TYPE="radio" NAME="a" onClick="this.form.meal.options[0]. selected=1">$10<BR> <INPUT TYPE="radio" NAME="a"onClick="this.form.meal.options[1]. selected=1">$15<BR> <INPUT TYPE="radio" NAME="a"onClick="this.form.meal.options2]. selected=1">$20<BR></P> <B>Your dinner tonite is:</B><BR> <SELECT NAME="meal" > <OPTION VALUE="$10">Pizza <OPTION VALUE="$15">Extra Cheese Pizza <OPTION VALUE="$20">Extra Veggies Pizza </SELECT> </FORM></BODY> </HTML>

Figure 7.11 You can really confuse your users by having one form element change another. Be sure to think through your design.

CAUTION: With text boxes, the information displayed in the box is the value property. With select, the value property is not displayed. This is like option buttons and check boxes. So, don't change the value property of select and expect the display to change.

Example: An Application Using Advanced Navigation


This example is designed to explain the concepts discussed in this chapter. There are several suggestions on how you can make them more robust, but the key is the explanation. You will see how links, as well as anchors, can be dynamic. The select element is also used. Internet Tri-Eye is truly a kaleidoscope on the Web. With a few clicks, you can see New York, Hollywood, and Pike's Peak; Hong Kong, the Antarctic, and the Netherlands; or fish, a cat, and some ants. It is a great way to demonstrate not only JScript, but also the Web. The purpose of Internet Tri-Eye is to simultaneously display pictures from multiple cameras connected to the Internet. You select a set, say the U.S., International, or Animals. Then you click Show Picture to display one view of the world. Further information about each camera is also available.

Expand the View with Frames


Listing 7.15 shows the basic layout for the browser window. This layout is defined by the HTML page. The file is named trieye.htm and can be found on the CD-ROM. The window is divided into two frames, with the top frame divided into three additional frames.

NOTE: Internet Tri-Eye is a JScript application that uses frames. The entire application consists of five files: trieye.htm, one.htm, two.htm, three.htm, and guide. htm. The code for the first four files is in Listing 7.15. The last file, guide.htm, is developed as you work through this section. The completed application is available on the CD-ROM. You start the application by loading the file trieye.htm.

Listing 7.15 trieye.htm--Frameset for Internet Tri-Eye Application

<HTML><HEAD><TITLE>Internet Tri-Eye</TITLE></HEAD> <FRAMESET ROWS="*,200"> <FRAMESET COLS="33%,34%, 33%"> <FRAME SRC="one.htm" NAME="one"> <FRAME SRC="two.htm" NAME="two"> <FRAME SRC="three.htm" NAME="three"> </FRAMESET> <FRAME SRC="guide.htm" NAME="guide"> <NOFRAMES> <H1>Internet Tri-Eye</H1> <P><B>Internet Tri-Eye</B> is a demonstration of several features of JScript. To view and use this program you need a JScript or Javascript compatible browser. </NOFRAMES> </FRAMESET> </HTML> The content of the top three frames, the eyes, are files one.htm, two.htm, and three.htm (see Listings 7.16, 7.17, and 7.18). These are extremely small files that are used only when the application is first loaded.

Listing 7.16 one.htm--Initial Contents of Frame One for Tri-Eye


<HTML><HEAD></HEAD><BODY> <H1>Eye One</H2> </BODY></HTML>

Listing 7.17 two.htm--Initial Contents of Frame Two for Tri-Eye


<HTML><HEAD></HEAD><BODY> <H1>Eye Two</H2> </BODY></HTML>

Listing 7.18 three.htm--Initial Contents of Frame Three for Tri-Eye


<HTML><HEAD></HEAD><BODY> <H1>Eye Tri</H2> Files two.htm and three.htm are identical to the file one.htm except that the headline is changed to "Eye Two" and "Eye Three," respectively. The guts of Tri-Eye and all of the JScript code are found

in the file guide.htm. This file is the contents of the lower frame. As we progress in building the application, all of the changes are made to this file. So far, the four files, trieye.htm, one.htm, two. htm, and three.htm, are complete.

TIP: Most people find it easier to write JScript after doing the layout. Do your frames, your tables, your controls, and even some windows; then write the code to pull it all together.

Objects for Tri-Eye


Now that we have the framework, the next step is to set up objects for each "eye," or camera. We start by defining an object called cam. The object has three properties: the description of the camera, the name for the anchor (more later), and the URL for the image. The code in guide.htm starts with the standard header, the SCRIPT tag, and then defines the cam object. Listing 7.19 shows the first part of the guide.htm file.

Listing 7.19 guide.htm--Start of the Coding for Tri-Eye


<HTML><HEAD><TITLE>Internet Tri-Eye by Ray Daly</HEAD> <SCRIPT LANGUAGE="JScript"> <!-function cam (name, anchor, rul) { this.name = name this. anchor = anchor this.url = url } Then, for each camera, a new object is established. In this example, there are nine different cameras, so create nine different objects labeled cam1 to cam9. Listing 7.20 shows this portion of the code. You can add more if you like.

Listing 7.20 guide.htm--Setting Properties for Cam Objects for Tri-Eye


cam1 = new cam ("Hollywood, CA", "#Hollywood", "http://hollywood. bhi.hollywood.ca.us:8000/pictures/image01.gif") cam2 = new cam ("Pikes Pike, CO", "#Pikes", "http://www.softronics.com/peak_cam/cam.jpg") cam3 = new cam ("New York City, NY", "#New York City", "http://www.metaverse.com/gate/images/empire.jpg") cam4 = new cam ("Zandvoort, NE", "#Zandvoort", "http://www.dataplace.nl//images/zandv-gr.jpg") cam5 = new cam ("Hong Kong", "#Hong Kong",

"http://www.hkstar.com/images/capture1.jpg") cam6 = new cam (" Australian Antarctic", "#Antartic", "http://www. antdiv.gov.au/aad/exop/sfo/mawson/video.gif") cam7 = new cam ("Fishcam", "#Fishcam", "http://www.netscape.com/fishcam/fishcam.gif") cam8 = new cam ("Mojo - Cat", "#Mojo", "http://www.lowcomdom.com/mojo.gif") cam9 = new cam ("Steve's Ant Farm", "#Ant Farm", "http://sec.dgsys.com/images/zANTPIX/Untitled.jpeg") We now have nine different objects. In order to make it easier to reference these objects, create another object called camset (see Listing 7.21). From this object, an object called camindex is created. The first property in camindex is cam1, the second is cam2, and so on. Thus, to get the contents of cam5, you reference the fifth element in camindex.

Listing 7.21 guide.htm--Putting Nine Objects into One for Tri-Eye


function camset (eye1, eye2, eye3, eye4, eye5, eye6, eye7, eye8, eye9 ) { this.eye1 = eye1 this.eye2 = eye2 this.eye3 = eye3 this.eye4 = eye4 this.eye5 = eye5 this.eye6 = eye6 this.eye7 = eye7 this.eye8 = eye8 this.eye9 = eye9 } camindex = new camset (cam1, cam2, cam3, cam4, cam5, cam6, cam7, cam8, cam9) We do not need to create so many different objects, but this method seems more straightforward than the other options. If you are good with objects, have fun minimizing. The final two lines of the JScript for this section initialize two variables to one, as follows: var setnumber=1 var camnumber=1 //--> </SCRIPT> </HEAD> Controls. To make anything happen with Internet Tri-Eye, controls need to be added. So far, all we have in guide.htm is the JScript defining the objects. Now, the HTML code is added for the controls

(see Listing 7.22). To hold the controls, there is a table of three rows and three columns. Across the entire first row is a button and a select element. The button is very simple and labeled About. When you click it, an Alert window tells you about Internet Tri-Eye. The next element in the top row is a SELECT box. Here, you select which set of cameras you want to look at. The first three cameras are locations in the United States, the next three are international, and the last three are pets. When you make a selection, it sets the variable setnumber to 1 or 2 or 3.

Listing 7.22 guide.htm--Laying Out the Control Table for Tri-Eye


<BODY><FORM> <TABLE BORDER="1" WIDTH="100%"> <TR> <TD ALIGN=CENTER COLSPAN=3> <A NAME="top"> <INPUT TYPE="button" NAME="aboutTE" VALUE="About Tri-Eye" onClick="alert(`Tri-Eye is a demo from the book: JScript Special Edition')"> <SELECT NAME="setselect" onBlur="setnumber=setselect.selectedIndex+1"> <OPTION VALUE="US" SELECTED> U.S. <OPTION VALUE="World">World <OPTION VALUE="Pets">Pets </SELECT> </TD> </TR><TR> <TD ALIGN=CENTER VALIGN=TOP WIDTH="33%"> <A HREF=" "onClick="this.href=findHREF(1)" " TARGET="one">Show picture One </A> </TD> <TD ALIGN=CENTER VALIGN=TOP WIDTH="34%"> <A HREF=" "onClick="this.href=findHREF(2)" " TARGET="two">Show picture Two</A> </TD> <TD ALIGN=CENTER VALIGN=TOP WIDTH="33%"> <A HREF=" "onClick="this.href=findHREF(3)" " TARGET="three">Show picture Tri</A> </TD> </TR><TR> <TD ALIGN=CENTER> <A HREF=" "onClick="this.href=findHASH(1)" " NAME="Info1">---Info--</A> </TD> <TD ALIGN=CENTER> <A HREF=" "onClick="this.href=findHASH(2)" " NAME="Info1">---Info---

</A> </TD> <TD ALIGN=CENTER> <A HREF=" "onClick="this.href=findHASH(2)" " NAME="Info1">---Info--</A> </TD></TR> </TABLE> The final two rows of controls are for demonstrating dynamic links and anchors.

Dynamic Links
The middle row of controls is for the dynamic links. When you click these links, one picture from one camera is displayed. There is one control for each of the "eyes." The code we need pulls in the proper URL, given "eye" 1, 2, or 3, and is based on the set chosen with the SELECT box (see Listing 7.23). These variables are camnumber and setnumber.

Listing 7.23 guide.htm--findHREF Function for Tri-Eye


function findHREF (eye) { // ...eye is 1, 2 or 3 -- the target frame indexnumber = (eye-1) +( 3 * (setnumber -1) //the value of indexnumber is between 0 and 8 return camindexindexnumber].url } //returns the url of the camera This code is added between the <SCRIPT> tags. Once you have the URL, the code is fairly simple. When the hyperlink is clicked, the findHREF function is called. It returns the URL, and the href property is changed. The target for the URL is the appropriate "eye" frame. Change the href property to the URL. For "eye" 3, the code is:

<A HREF=" "onClick="this.href=findHREF(3)" " TARGET="three">Show picture Tri</A> For simplicity, the hyperlink text is "Show picture One" or "Two" or "Tri." To polish up the application, an icon could be used here.

Anchors to Complete the Story


So far, Internet Tri-Eye is already spectacular. It is a true kaleidoscope on the world. However, it does not tell us anything about these pictures. Anchors are used two different ways to complete the story. Anchors to the Reference Information. The final row of the controls is for information links.

Click the text ---Info--- and the frame scrolls down to a description of the site. For this example, there is a short, three-line description with a link to the host site if you would like more information. When the objects were created for this page, anchors were included. So, the same technique that was used above for links is now used for anchors. The function has only a minor difference: It returns the anchor property. function findHASH (eye) { // ...eye is 1, 2 or 3 -- the target frame indexnumber = (eye-1) + ( 3 * (setnumber -1)) return camindexindexnumber].anchor } The control itself is also similar:

<A HREF=" "onClick="this.href=findHASH(3)" " NAME="Info1">--- Info ---</A>

Anchors to Take Me Back. Once you read the information on the picture, you probably want to go back to the controls. Notice that the title of each description is followed by a hyperlink labeled (top). What you may not have noticed is that there is no anchor with the name top. Instead, (top) is the name of the About button. So, click (top), and the About button will return to the top of the page. Listing 7.24 completes the file guide.htm. <A HREF="#top">(top)</A>

NOTE: This code completes the guide.htm file (see Listing 7.24). All five files that make up this application are found on the CD-ROM. You start the application by loading trieye.htm.

Listing 7.24 guide.htm--Anchor Section for Tri-Eye


<CENTER><H1>Tri-Eye Guide</H1></CENTER> <DL><DT><A NAME="Hollywood">Hollywood, CA</A> <I><A HREF="#top"> (top)</A> </I></DT> <DD>Not your typical American street corner, this is <A HREF="http://www.geocities.com/cgi-bin/main/BHI/look. html">Hollywood and Vine from GeoCities</A>. Just remember that &quot;nobody walks in L. A.&quot;</DD>

<DT><A NAME="Pikes">Pikes Pike, CO</A> <I><A HREF="#top">(top)</A></ I></DT> <DD>One of America's most famous mountains. <A HREF="http://www.softronics.com/peak_cam.html">Pikes Peak Cam from Softronics</A> gives you the view from Colorado Springs.</DD> <DT><A NAME="NYC">New York City, NY</A> <I><A HREF="#top">(top)</ A></I></DT> <DD>New York City's most famous building. <A HREF="http://www.metaverse.com/empire.html">Empire Cam from Metaverse</A> has a view across part of the skyline. Check the weather.</DD> <DT><A NAME="Zandvoort">Zandvoort, the Netherlands</A> <I><A HREF="#top">(top)</A></I></DT> <DD>No close ups of the people on the beach. This <A HREF="http://www.dataplace.nl/dp/pages/foto.htm">Livecam from Dataplace </A> points northwest across a traffic circle and up the beach.</DD> <DT><A NAME="Hong">Hong Kong</A> <I><A HREF="#top">(top)</A></I></ DT> <DD>Street scene that is colorful almost anytime. The <A HREF="http://www.hkstar.com/starcam.html">STARcam from HK Star Internet Ltd.</A> shows more cars than people.</DD> <DT><A NAME="Antarctic">Australian Antarctic</A> <I><A HREF="#top"> (top)</A></I></DT> <DD>While often black, some previous pictures are available. The <A HREF="http://www.antdiv.gov.au/aad/exop/sfo/mawson/video. html">camera at Mawson Station</A> captures the pictures and though a variety of technology gets it to your desk.</DD> <DT><A NAME="Fishcam">Fishcam</A> <I><A HREF="#top">(top)</A></I></ DT> <DD>Perhaps the most famous fish in the world. <A HREF="http://www.netscape.com/fishcam/fishcam.html">Fishcam from Netscape</A> now has multiple cameras and formats. Who ever imagined an aquarium as a revenue source?</DD> <DT><A NAME="Mojo">Mojo</A> <I><A HREF="#top">(top)</A></I></DT> <DD>You won't believe the technology used to bring you these images. <A HREF="http://www.lowcomdom.com/mojo_cam.html">Mojo-Cam</A> isn't from a fixed view so it worth following.</DD> <DT><A NAME="Ant">Ant Farm</A> <I><A HREF="#top">(top)</A></I></DT>

<DD>Some people won't even think that this is a safe distance away. <A HREF="http://sec.dgsys.com/AntFarm.html">Steve's Ant Farm</A> also has a movie available.</DD></DL></FORM></BODY></HTML> Now, Internet Tri-Eye is complete. Figure 7.12 shows its top-level display. Figure 7.12 The Tri-Eye Web page is your window on the world.

Example: Tri-Eye FTP Auto Dialer


Trying to FTP a popular new piece of Internet software can be frustrating. You click a link, and it seems like minutes before you're asked to try again later because the site is busy. We will modify the Internet Tri-Eye application to create a Tri-Eye Auto Dialer. To do this, we will replace the file guide. htm with a new file, guideftp.htm, which can also be found on the CD-ROM. You can create the Tri-Eye FTP Auto Dialer with a simple modification to one file of the Internet TriEye application. Simply change the values of the properties for each cam object in the guide.htm file. These properties are the URLs for the information displayed in each of the upper frames. For example, to get the Windows NT version of Navigator 2.0 from Netscape's FTP site, you would use an URL such as: ftp://ftp2.netscape.com/2.0/windows/n32e20.exe Do the same for each FTP location just by changing the host from ftp2 to ftp3, and so on; the last one is ftp10. The function looks nearly the same; only the contents of the properties have changed (see Listing 7.25). The top-level FTP Auto Dialer window is shown in Figure 7.13.

Listing 7.25 guideftp.htm--Redefined cam Object for Tri-Eye FTP Auto Dialer
function cam (name, anchor, url) { this.name = name this.anchor = anchor this.url = url } cam1 = new cam ("FTP2", "#Netscape com/2.0/windows/n32e20.exe") cam2 = new cam ("FTP3", "#Netscape com/2.0/windows/n32e20.exe") cam3 = new cam ("FTP4", "#Netscape com/2.0/windows/n32e20.exe") cam4 = new cam ("FTP5", "#Netscape

FTP", "ftp://ftp2.netscape. FTP", "ftp://ftp3.netscape. FTP", "ftp://ftp4.netscape. FTP", "ftp://ftp5.netscape.

com/2.0/windows/n32e20.exe") cam5 = new cam ("FTP6", "#Netscape FTP", "ftp://ftp6.netscape. com/2.0/windows/n32e20.exe") cam6 = new cam ("FTP7", "#Netscape FTP", "ftp://ftp7.netscape. com/2.0/windows/n32e20.exe") cam7 = new cam ("FTP8", "#Netscape FTP", "ftp://ftp8.netscape. com/2.0/windows/n32e20.exe") cam8 = new cam ("FTP9", "#Netscape FTP", "ftp://ftp9.netscape. com/2.0/windows/n32e20.exe") cam9 = new cam ("FTP10", "#Netscape FTP", "ftp://ftp10.netscape. com/2.0/windows/n32e20.exe") Figure 7.13 Tri-Eye FTP Auto Dialer will make multiple attempts to make an FTP connection. This should increase your chances for success.

Other Possible Improvements to and Uses of Internet Tri-Eye


Internet Tri-Eye was written to keep the code simple to explain, not to dazzle you with graphics. The following are several suggestions for improving Tri-Eye or expanding its use:
q

When you click ---Info---, the control scrolls off the frame. Add one frame just for the table of controls. Show the information in another frame. Don't use any frames, but put everything in its own window. Click the control to show a picture, and it pops up as a new window. Then, every "eye" can be free-floating. Replace the text links with icons. Although ---Info--- is easy to explain in a book, the page will look better with graphics. Add more cameras. People are hooking up cameras all the time: some silly, some beautiful, and some scenic. Grab your favorite, and create some more objects. Instead of doing cameras, do magazines or other publications. Take a collection of magazines and put them in as objects. This would obviously work much better with windows instead of frames.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us.

1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Chapter 8 Dynamic HTML and IE Objects


q

Dynamic HTML and IE Objects r JScript Object Hierarchy s Browser Windows s Dynamic Window Creation s Window Status s The Location Object s The History Object s Security Aspects of JScript Objects s The Document Object r Dynamic Documents s Restrictions on document.Write s Using Nascent Documents s A Page Generated Entirely by JScript s Dynamically Rewriting Your Page s The openNote() Script Revisited

Dynamic HTML and IE Objects


q q q q q q

Some of the main topics in this chapter are Write JScript statements that can access objects in windows and documents Create and format new browser windows Add new elements by rewriting documents dynamically Create entirely new documents for JScript Manipulate the history list and the location object

This chapter describes the creation of dynamic documents and windows, as well as the interaction between windows and their components. This chapter presumes that you now have a working knowledge of JScript syntax; the material covered is somewhat more complex than in earlier chapters (see Chapter 4, "JScript Objects"). The first theme of the chapter is the creation of pop-up windows. The entire content of those windows is defined by a creation function, rather than an URL. We will examine various examples, including pop-ups with text, pop-ups with buttons, and editable pop-ups. We will next examine the history, status, and location objects. You will see how to hurl the

user to a specific URL on the history list, how to examine the various parts of the location object, and how to store and retrieve information using the search property of the location object. Finally, you will learn how to create dynamic documents. In fact, you will create a page entirely from JScript. You will also learn how to rewrite pages on-the-fly.

JScript Object Hierarchy


You have already learned a lot about objects in JScript. In fact, the previous four chapters have been devoted to exploring the various JScript objects and their uses. You have already been exposed to the various built-in objects and HTML objects that JScript provides. To go further and explore dynamic HTML creation, we must first take a closer look at the hierarchy of objects in JScript. If you are familiar with any object-oriented languages, you expect an object hierarchy to begin with a generic object from which all other objects are descendants or children. Unfortunately, the JScript object hierarchy does not really follow this model. It might be best described as a system of ownership, and, even then, the analogy is not really exact. For example, a window that creates another window could be thought of as the parent of the new window. However, if you try to refer to the original window from the child by saying parent.someobject, it may not work. On the other hand, frames within a frameset have a parent-child relationship with the original window, and asking for parent.someobject will likely yield the object. Other ownership relationships are not characterized by a parent-child relationship at all. For example, form elements belong to a form, but to obtain the form, you use this.form--not this.parent. With these disconcerting thoughts in mind, let's attempt to sort out the dependencies among browser objects. The browser is, in a way, the parent of all other JScript objects. It is the executable that runs the browser. The browser is responsible for the creation of all browser windows. It is also responsible for responding to general window events. The browser is not a visual object. You cannot see it. You interact with it only through its visual constructs: its windows.

Browser Windows
Most browser window components can be manipulated only in a yes/no fashion at the time of window creation. These include the menu, the button bar, the location display, the status display, history list display, and scroll bars. At the time of window creation, you can also determine whether the window can be resized, as well as finding its dimensions. This might seem like a significant restriction. By rewriting the document, however, you can change the contents of a window. This technique enables you to change the values of form elements, the content of the status bar, the position of the pointer in the history list, and the location (the URL that the window contains) at any time. Table 8.1 lists these various elements, when they can be modified, and how they can be modified. Note that the last two items in this table are not really window elements: They control what is displayed, but are not explicitly displayed themselves.

Table 8.1 Modification Rules for JScript Controls Object Button bar Menu Status Bar History Document Many form Location History list When How Rewrite? NA NA NA NA NA

Window creation Yes/No Window creation Yes/No Window creation Yes/No Window creation Yes/No During rewrite Anytime Anytime Anytime

Location display Window creation Yes/No

Complete NA Complete No element properties Complete No Complete Yes Complete Yes

Status bar content Anytime

Dynamic Window Creation


One of the more advanced projects later in this book is the creation of a sticky notes application (in the "Dynamic Documents" section). To do that, you need to have a small note window in which to present the note. Let's create a primordial note window now. To do that, you must already have a window open with an element that enables you to call a JScript function (such as a button with an onClick handler). This base window is the parent of the child note window. The child can always find its parent with self.parent, but the parent can refer to the child only by its name. There is no self.child[] reference, nor is there a windows array available to JScript because of security concerns.

CAUTION: Internet Explorer is a mimic. If you create a window under a JScript control, the next window that is created by IE will have the same dimensions as the last window created by JScript.

The element that we will use is an image that behaves as a button, which is triggered by an HREF=javascript: :myfunc included in the LINK tag. This works very well if you need to call only one function and you need no return value. When you try to use this mechanism in a window constructed on-the-fly, however, the image refuses to display. In fact, any image that uses relative addressing refuses to display in a dynamic window. The solution is either to use a completely static reference for the image or to set the base directory of your page with <BASE>path</BASE> in the header. This latter approach helps JScript find the image. If you need an object that will be accessed later, you might want to use a form input element,

rather than one of these button images. JScript will have less trouble finding it. The following three steps are necessary to use an image as a button for executing a JScript function: 1. Write an appropriate HTML declaration for the desired image. 2. Enclose this HTML declaration within reference tags. 3. Resolve the HREF to a JScript function declaration. These three steps are shown in Listing 8.1.

Listing 8.1 Creating a Button Image


<IMG WIDTH=23 HEIGHT=22 VSPACE=2 HSPACE= 2 ALIGN=LEFT SRC="Images/gobtn.gif" BORDER=0> <A HREF='xxxxxx'><IMG WIDTH=23 HEIGHT=22 VSPACE=2 HSPACE=2 ALIGN=LEFT SRC="Images/gobtn.gif" BORDER=0><A> <A HREF='javascript: openNote'><IMG WIDTH=23 HEIGHT=22 VSPACE=2 HSPACE= 2 ALIGN=LEFT SRC="Images/gobtn.gif" BORDER=0><A> The function used in this example is the openNote() function, the source for which is given in Listing 8.2. Before we plunge into this code, it is worthwhile to notice that the border has explicitly been set to zero. This is the only way you can keep the browser from drawing a border around your image if it is within a reference statement. Listing 8.2 contains the HTML for the base window with the button that creates a note. It includes the openNotes() function in a header script. Once you open a note window, make sure you close it before it gets lost. Internet Explorer will not open a second window by the same name; it just updates the first one. When this code is executed by pressing the Make Note button, you will see something like Figure 8.1.

Listing 8.2 Creating a New Window in JScript


<HTML> <HEAD> <TITLE>Opening a Window with JScript</TITLE> <SCRIPT> //window globals var aNoteWin function openNote(topic) { aPopUp= window.open(`','Note','toobar=no,location=no, directories=no,status=no,scrollbars=yes,resizable=yes, copyhistory=no,width=300,height=200')

ndoc= aPopUp.document astr ='<HTML><HEAD><BR><TITLE>' + topic + `</TITLE>' astr +='</HEAD>' astr +='<BODY>' astr +=topic + `<BR>' astr +='</BODY></HTML>' ndoc.write(astr) ndoc.close() self.aNoteWin = aPopUp } function closeNote(which) { self.aNoteWin.close() } </SCRIPT> </HEAD> <BODY> <H3><BR><HR><BR></H3> <CENTER> <FONT SIZE=5 COLOR='darkred'><B>Example 1</B></FONT>: <FONT SIZE=5 COLOR='darkblue'><B>Opening a New Window</B></FONT> <FORM NAME='noteForm'> <INPUT TYPE='button' NAME='makeBtn' VALUE='Make Note' onclick='openNote("JoAnn Murphy at 7:00; bring salad")'> <INPUT TYPE='button' NAME='closeBtn' VALUE='Close note' onclick='closeNote()'> </FORM> </CENTER> <H3><BR><HR><BR></H3> </BODY> </HTML>

CAUTION: In a windows.open statement, there are three things to bear in mind. You need only the first two parameters (the URL, which can be empty, and the window name) to open a window. If you do not include the third parameter, the window attributes list, then the window will have all of its window attributes set to yes (present). If you specify any of the windows attributes, then you must include the whole list of at- tributes. Otherwise, the results will be unpredictable. Enclose the attributes list in quotation marks, separate the items with commas, and do not leave spaces.

Figure 8.1 Dynamically created windows may be tied to button events in JScript. This small script illustrates several points. First, you can set a window global by defining it outside of any function and preceding it with var. Here, we set the window global aNoteWin with var aNoteWin. This variable is global, so you could use it to refer to aNoteWin in other functions. Although we did not do so here, you might want to save a number of notes in an array. Second, when you create a window de novo via a script, and no URL is specified, the window document is still open, and you can write to it. Here we wrote the note topic and then closed the document. A window that you create can be as simple as the note window. However, you can also make this window quite complex. In order to do so, you must write everything to the document, including form elements, images, and JScript functions, before you close it. Listing 8.3 shows a second version of the openNote() function. This more elaborate version furnishes the note window with two buttons, including onClick handlers, the topic text, a warning message, and two JScript functions. It may be found in the file C8-1.htm on the CD-ROM. Note that the save function is stubbed. The topic of data storage is discussed in Chapter 17, "Using Frames and Cookies." All the display elements are neatly wrapped in a table. Data can be stored transiently in the location.search property and persisently in cookies; both topics are discussed in the "Persistent Data Storage" section of Chapter 17, "Using Frames and Cookies."

Listing 8.3 C8-1.htm--A More Sophisticated Notes Window


function openNote(topic) { aPopUp= window.open(`','Note','toobar=no,location=no, directories=no,status=no,scrollbars=yes,resizable=yes, copyhistory=no,width=300,height=200') ndoc= aPopUp.document astr ='<HTML><HEAD><TITLE>' + topic + `</TITLE>' astr +='<SCRIPT>' astr +='function closeNote(aName){` astr +='self.close()' astr +='}' astr +='function saveNote(aName){` astr +='}' astr +='<\/SCRIPT>' astr +='</HEAD>' astr +='<BODY>' astr +='<FORM>' astr +='<TABLE ALIGN=LEFT BORDER><TR ALIGN=CENTER><TD>' astr +='<INPUT TYPE=button NAME=saveBtn VALUE="Save" ONCLICK="saveNote()">'

astr +='</TD>' astr +='<TD ROWSPAN=4>' + topic astr +='</TD>' astr +='</TR><TR ALIGN=CENTER><TD>' astr +='<INPUT TYPE=button NAME=closeBtn VALUE="Close" ONCLICK="closeNote()">' astr +='</TD></TR>' astr +='<TR><TD><BR></TD></TR>' astr +='<TR><TD><BR></TD></TR>' astr +='</TABLE>' astr +='</FORM>' astr +='<BR CLEAR=ALL><H3><BR></H3>' astr +='Note: Save button is not active yet' astr +='</BODY></HTML>' ndoc.write(astr) ndoc.close() self.aNoteWin = aPopUp }

Window Status
Internet Explorer keeps you apprised of which link or button your mouse pointer is over via its status bar. Occasionally, it sends you other messages via that method, too. Perhaps you have seen it busily scrolling text to catch your attention. The status (not the status bar itself) is a property of a window and is accessible to you as self.status = `Some message'. When you change the status, the browser immediately displays it in the status bar. You can also set a property called defaultStatus, which is the default message displayed in the status bar. Listing 8.4 illustrates the use of the status property in Internet Explorer. This code will be found in the file c8-2.htm on the CD-ROM.

Listing 8.4 c8-2.htm--Manipulating the Status Bar


<HTML> <HEAD> <TITLE>Manipulating the Status Bar</TITLE> <SCRIPT> // set up a window global so that the new window can be accessed // from all functions. var aStatWin = null function openStatus(defmsg,msg) { aStatWin=window.open(`','statWin','toobar=no,location=no, directories=no,status=yes,scrollbars=no,resizable=yes, copyhistory=no,width=550,height=2')

if (aStatWin != null) { aStatWin.document.write(`<FORM NAME="dform"> <INPUT TYPE=TEXT NAME="dummy"></FORM>') aStatWin.document.close() aStatWin.defaultStatus = defmsg aStatWin.status = msg setFocus() } } function setStatus() { if ( self.aStatWin == null ) alert(`Status window is closed!') else { self.aStatWin.status = document.statForm.statMsg.value setFocus() } } function setFocus() { self.aStatWin.document.dform.dummy.focus() } function myclose() { self.aStatWin.close() aStatWin = null } //This function is a work-around to make sure that the table // overlay is drawn correctly. function fixup() { blankWin=window.open(`','blankWin','toobar=no,location=no, ~ directories=no,status=yes,scrollbars=no,resizable=no, ~ copyhistory=no,width=600,height=450') blankWin.close() } </SCRIPT> </HEAD> <!-- fixup forces redraw of window after everything, including images,

has loaded. The redraw is necessary to enforce correct drawing of table overlays. --> <BODY onLoad='fixup()'> <H3><BR><HR><BR></H3> <CENTER> <FONT SIZE=5 COLOR='darkred'><B>Example : </B></FONT> <FONT SIZE=5 COLOR='darkblue'><B>Setting the Contents of the Status Bar</B></FONT> <H3><BR><HR><BR></H3> <H3><BR></H3> </CENTER> <CENTER> <FORM NAME='statForm'> <TABLE WIDTH=520 ALIGN=CENTER BORDER><TR ALIGN=CENTER><TD> <TABLE WIDTH=500 ALIGN=CENTER> <TR ALIGN=CENTER> <TD WIDTH=35 ALIGN=CENTER> <IMG WIDTH=48 HEIGHT=50 VSPACE=2 HSPACE= 2 ALIGN=CENTER SRC="Images/gotray2.gif"> </TD> <TD> <!-- <INPUT TYPE=button VALUE='Make Status Window' onClick='openStatus("Status is GO!", document.statForm.statMsg.value)'> --> <A HREF='javascript: openStatus("Status is GO!", document.statForm.statMsg.value)'> <IMG WIDTH=23 HEIGHT=22 VSPACE=2 HSPACE=2 ALIGN=absMiddle SRC="Images/gobtn1.gif" BORDER=0> Open Status Window</A> </TD> <TD ALIGN=LEFT > <A HREF='javascript: setStatus()'> <IMG WIDTH=23 HEIGHT=22 VSPACE=2 HSPACE=2 ALIGN=absMiddle SRC="Images/gobtn2.gif" BORDER=0> Set Status</A> </TD> <TD ALIGN=CENTER > <A HREF= `javascript: myclose()'> <IMG WIDTH=31 HEIGHT=30 VSPACE=2 HSPACE= 2 ALIGN=absMiddle BORDER=0 SRC="Images/okbtn.gif"> Close Status </A> </TD> </TR> <TR ALIGN=CENTER>

<TD ALIGN=CENTER COLSPAN=4> Msg <INPUT TYPE=text NAME='statMsg' VALUE='Howdy!' SIZE= 50 MAXLENGTH=80> </TD> </TR> </TABLE> </TD></TR></TABLE> </FORM> </CENTER> <H3><BR></H3> </BODY> </HTML> This example builds a window with a status bar included. Just to make things interesting, we'll set the content of the status bar from the parent window. In addition, this script provides an example of the advanced HTML concept of table overlays, and an onLoad() handler, which provides a workaround for the browser's unpredictable order of drawing images. We will say a little more about table overlays below, when we discuss the fixup() function. The status window is created with a `javascript: openStatus(defMsg,msg)' link attached to an image. This function, openStatus(defMsg, msg), performs the following tasks:
q q

It creates a new window with everything turned off but the status bar. It checks that the window was actually created by examining aStatWin for a null value. It is important to perform this, because attempts to access objects in a nonexistent window will result in errors. The usual reason why a window will fail to be created is lack of memory. This routine aborts with a message if the window was not created. It places a dummy text field in aStatWin. This button is just used as an object to set the focus, so that we can bring the window to the front. Otherwise, small windows can get lost. It sets the initial and default status. Internet Explorer immediately makes its presence known by writing to your status bar.

We will set the status of the status window with a call to setStatus(). This call is made from a `javascript: setStatus(document.statForm.statMsg.value)' link attached to an image. The setStatus() function also checks to see whether aStatWin exists before it tries to address one of its objects. If aStatWin does exist, setStatus changes the content of its status bar. setStatus() then sets the focus on the dummy button in aStatWin to bring the window to the front. This is done by a call to the setFocus() method. The resulting window is shown in Figure 8.2. When you are done with the window, you can close it using an image button linked with a call to close function myclose(). The myclose() function simply closes aStatWin and makes sure that its value is reset to null. Note that it would have been unpleasant if we had named the close function simply close(). This is because there is a built-in window function called close. If we had named our function close(), JScript would not have complained, but when we clicked the

Close button, the built-in close() function would have been called, not ours. Figure 8.2 A status bar window may be created dynamically by the parent window. The function fixup() is worth looking at in more detail. The order in which the browser draws images depends upon where the images are coming from, whether they are in the cache, and whether their height and width are given explicitly. It can also depend on the size of the images. Extremely attractive presentations can be made by overlaying text and graphics on other graphics via the overlay feature of HTML tables. However, Internet Explorer will often draw your bottom image last when the page first loads. Scrolling the screen causes the correct redraw, but you cannot expect or require your users to do that. One way to force the redraw is to open and quickly close another window over your page. You need to do this after all of the page elements have been loaded. When this occurs, the browser sends an onLoad event, which you can capture in the <BODY> tag. The fixup() function ensures that all of the image buttons are visible. Although this is far from an ideal solution, it is effective. TIP: Always check that a newly created window exists before you try to address its properties or methods. Do this by checking to see whether the window is null. If it is null, use an alert to inform the user.

The Location Object


The location object essentially holds information about the URL to which the browser points. The browser reads this marked-up text from the server's disk and interprets it just as Microsoft Word reads and interprets a file on your disk. In addition to the URL, the location object also contains any post parameters of an HTML form submitted via a Submit button or your call to submit(). Because of this, you can use the location object for temporary storage. In Internet Explorer, the location consists of the following parts: protocol//hostname: (port) pathname search hash Protocol is the type of protocol used for this file. Examples are http, ftp, gopher, telnet, and file (for files on the local disk). Hostname and port are valid only when the document is on a remote server. They contain the domain name/IP address of the server and the server port, respectively. The Web port is a number denoting the type of service, and is usually 80 for http. The pathname is the path to the file that the browser displays. search includes any post parameters that are compiled when a form is submitted. hash is usually a link to a local anchor. The location object also has a host property, which consists of the combination of hostname

and port. The location object also has an extremely important property, known as href, which contains the entire URL. Finding Out Where You Are. This next example is a page that has no body. It is written entirely by the header script. As the page is written, it dissects the location object and lists all of its properties in a table. The host, port, and hostname properties will be nonempty only if you have loaded some page from a server. Listing 8.5 shows the code for the Location Display script. This code is in the file c8-3.htm on the CD-ROM.

Listing 8.5 c8-3.htm--Displaying the Properties of the Location Object


<HTML> <HEAD> <!- Created 08 Feb 1996 a2:41 PM 02:41 PM --> <TITLE>Parts of the Location Object</TITLE> <SCRIPT> var aline = `<H3><BR></H3><HR><H3><BR></H3>' var skip='<H3><BR></H3>' document.write(`<CENTER>') document.write(`<FONT SIZE=5 COLOR="darkred"><B>Example : </B></ FONT> <FONT SIZE=5 COLOR="darkblue"> ~ <B>What\'s in the Location Object?</B></FONT>') document.write(`<BR>') document.write(`<BLOCKQUOTE><BLOCKQUOTE>If you are viewing this document from your hard disk, host, hostname, and port will be empty.</BLOCKQUOTE></BLOCKQUOTE>') document.write(`<BR>') document.write(`<CENTER><TABLE ALIGN= CENTER BORDER CELLPADDING=3>') document.write(`<TR><TD><B>Property</B></TD><TD ALIGN=CENTER> <B>Value</B></TD></TR>') document.write(`<TR><TD>href</TD><TD>' + location.href + `</TD></ TR>') document.write(`<TR><TD>protocol</TD><TD>' + location.protocol + `</TD></TR>') document.write(`<TR><TD>hostname</TD><TD>' + location.hostname + `</TD></TR>') document.write(`<TR><TD>host</TD><TD>' + location.host + `</TD></ TR>') document.write(`<TR><TD>port</TD><TD>' + location.port + `</TD></ TR>') document.write(`<TR><TD>pathname</TD><TD>' + location.pathname + `</TD></TR>')

document.write(`<TR><TD>search</TD><TD>' + location.search + `</TD></TR>') document.write(`<TR><TD>hash</TD><TD>' + location.hash + `</TD></ TR>') document.write(`</TABLE></CENTER>') document.write(aline) document.write(`<CENTER>') document.write(aline) </SCRIPT> </HEAD> </HTML> Sending the User Elsewhere. Not only can you obtain useful information by examining the location object, you can also modify it and send the user elsewhere. This is useful if you should want to dynamically generate an URL or a reference to an anchor. The example shown in Listing 8.6 builds an URL dynamically and sends the current browser to that URL. This code implements a "Message Center," which retrieves messages from URLs created via button clicks. Four users have been created to demonstrate this aspect of the location object. The CD-ROM file c8-4.htm contains this message center code.

Listing 8.6 c8-4.htm--Modifying the Current URL Dynamically


<HEAD> <!- Created 08 Feb 1996 a4:08 PM 04:08 PM --> <TITLE>Message Center</TITLE> <SCRIPT> function getMessage(who) { loc = self.location nloc = "" + lock = nloc.lastIndexOf(`\\') nnloc = nloc.substring(0,k+1) + who.value + `.htm' self.location = nnloc } </SCRIPT> </HEAD> <BODY> <CENTER><HR> <FONT SIZE=5 COLOR='darkred'><B>Example 4</B></FONT>: <FONT SIZE=5 COLOR='darkblue'><B>Moving Around Dynamically</B></FONT><BR> <HR><FONT SIZE=6 COLOR='darkslateblue'><B>Message Center</B></ FONT><BR> </CENTER> <CENTER> <FORM> <TABLE BORDER ALIGN=CENTER><TR><TD>

<INPUT TYPE=radio NAME='getMsgR' VALUE='John' onClick='getMessage(this)'>John <INPUT TYPE=radio NAME='getMsgR' VALUE='George' onClick='getMessage(this)'>George <INPUT TYPE=radio NAME='getMsgR' VALUE='Ken' onClick='getMessage(this)'>Ken <INPUT TYPE=radio NAME='getMsgR' VALUE='Julie' onClick='getMessage(this)'>Julie <INPUT TYPE=hidden NAME='translate' VALUE=''> </TD></TR></TABLE> </FORM> </CENTER> <H3><BR><HR><BR></H3> <H3><BR><HR SIZE=5 WIDTH=80%><BR></H3> </BODY> </HTML> The script works by first obtaining the current location. It then strips off the file name and replaces it with the value of the option button clicked. It also makes sure to tack on the suffix .HTM. This presumes that the message HTML files are in the same directory as the current page. However, it would be easy enough to build in a subdirectory name just for the messages, or even have a separate subdirectory for each person. The location object is then set to the newly constructed URL. Setting the location object retrieves the file at that location. In our example, this file represents the set of messages for the particular user whose button was pressed.

TIP: You can force a page to be reloaded by setting the location object to the URL corresponding to that page.

Using the Search Property. When you submit a form, all the values of the various form elements are retrieved, parsed, and concatenated with the location object; they are placed after the path and preceded by question marks (?). The value of location.search is precisely that string, including the question mark (?). This string is not just a simple list of element contents, however. Each element value is placed in the string in the form `elementName=elementValue' and followed by an ampersand (&). Any nonalphanumeric characters are coded or escaped. The ASCII value of any such character is changed into a two-digit hex number preceded by a percent sign (%). If text field or textarea elements have multiple words, these words are separated by a plus sign (+). Consequently, when you get the location.search string, you have to decode it to get the various form elements that it contains. The section on "Global and Local Variables" in Chapter 9, "Creating Your Own JScript Objects," discusses character encoding in more detail.

You can place your own form element values, or anything else, in the location's search property. As long as you precede it with a question mark (?), location.search will retrieve it. However, not all nonalphanumeric characters can be placed in the string or retrieved intact. If you are going to concoct a homegrown search string, you may need either to encode the parameters yourself or not allow nonalphanumeric characters. Listing 8.7 is a simple page that shows you how to manipulate location.search.

NOTE: The current release of Internet Explorer severely limits the uses of the location. search property. In most cases, it will be empty on document reload.

Listing 8.7 Using the Search Property of the Location Object


<HTML> <HEAD> <!- Created 08 Feb 1996 a6:10 PM 06:10 PM --> <TITLE>Forcing a Reload with Location</TITLE> <SCRIPT> function reloadMe() { astr = document.nameForm.myName.value nastr= self.location.pathname + `?' + astr self.location = nastr } function clearUp() { self.location = self.location.pathname } if (self.location.search != null && self.location.search !='') { document.write(`<CENTER><FONT SIZE=4 COLOR="darkslategray"><B> Form Entry Data: </B></FONT></CENTER>') document.write(`<CENTER><FONT SIZE=4 COLOR="red"><B>' + self.location.search + `</B></FONT></CENTER>') } </SCRIPT> </HEAD> <H3><HR></H3> <CENTER><FONT SIZE=6 COLOR="blue"><B>Forcing a Reload with ~

Location</B></FONT></CENTER> <H3><BR><HR><BR></H3> <CENTER> <FORM NAME=nameForm> <INPUT TYPE=text NAME=myName VALUE='abracadabra&#^$()'> <INPUT TYPE=button NAME=reloadBtn VALUE='Reload Page' onClick='reloadMe()'> <INPUT TYPE=button NAME=submitBtn VALUE= `Submit Form' onClick='this.form.submit()'> <INPUT TYPE=button NAME=clearBtn VALUE= `Clear' onClick='clearUp()'> <INPUT TYPE=hidden NAME=hideFld> </FORM> </CENTER> <H3><BR><HR><BR></H3> <H3><BR><HR SIZE=5 WIDTH=80%><BR></H3> </BODY> </HTML> A script in the <HEAD> part of an HTML document can pick up the command-line parameters with location.search and write something to the document being loaded based on what it finds. This example just reads the parameter string and writes it for you at the head of the page. Note that this write is guarded by a test to see whether location.search is null or empty. If location. search is not a valid string, and you attempt to parse it into variables that are used later, you will encounter error after error. Always test for a null string or an empty string. The code in Listing 8.7 has two useful functions. ClearUp() simply strips the search string from the location by setting the location object to location.path. The reloadMe() function takes the value from the text box and adds it to location.path. It then sets the location to that result.

The History Object


The history object is a list that contains the locations of all the URLs that you have visited. You can move backward and forward through the history list with history.back and history. forward. You can also move around in the list in a relative fashion with history.go(). This function takes a positive or negative integer argument and moves you that many URLs forward or backward in the history list. The only property of a history list you can access is its length, which is the number of items in the list. You can neither set nor retrieve history list items. To show how to manipulate the history list, we'll build another pop-up window that boasts only a Close button and four directional buttons. The buttons enable you to manipulate the history list of the parent window. You can move backward and forward by one step or five. This code is shown in Listing 8.8, and will be found in the file c8-5.htm on the CD-ROM.

Listing 8.8 c8-5.htm--Using the History Object in a Pop-Up Window


<HTML> <HEAD> <!- Created 08 Feb 1996 a9:21 PM 09:21 PM --> <TITLE>Running through the History List</TITLE> <SCRIPT> var aNoteWin var creat function openPopup() { aPopUp= window.open(`','Note','toobar=no,location=no, directories=no,status=no,scrollbars=no,resizable=no, copyhistory=no,width=110,height=150') ndoc= aPopUp.document astr ='<HTML><HEAD><TITLE>Window Scroller</TITLE>' astr +='<SCRIPT>' astr +='var creat\n' astr +='function closeNote(aName){` astr +='self.close()' astr +='}\n' astr +='function saveNote(aName){` astr +='}\n' astr +='function goNext(){` astr +='creat.window.history.forward()\n' astr +='}\n' astr +='function goBack(){` astr +='creat.window.history.back()\n' astr +='}\n' astr +='function goBackFive(){` astr += `creat.window.history.go(-5)\n' astr +='}\n' astr +='function goNextFive(){` astr +='creat.window.history.go(5)\n' astr +='}\n' astr +='<\/SCRIPT>' astr +='</HEAD>' astr ='<BODY>' astr +='<FORM NAME="popForm">' astr +='<TABLE ALIGN=LEFT BORDER>' astr +='</TR><TR ALIGN=CENTER><TD>' astr +='<INPUT TYPE=button NAME="closeBtn" VALUE="Close" ONCLICK="closePopUp()">' astr +='</TD>' astr +='</TR>'

astr +='<TR ALIGN=CENTER><TD>' astr +='<INPUT TYPE="button" NAME="startBtn" VALUE="<<" onclick="goBackFive()">' astr +='<INPUT TYPE="button" NAME="backBtn" VALUE="<" onclick="goBack()">' astr +='<INPUT TYPE="button" NAME="nextBtn" VALUE=">" onclick="goNext()">' astr +='<INPUT TYPE="button" NAME="endBtn" VALUE=">>" onclick="goNextFive()">' astr +='</TD></TR>' astr +='<TR><TD>' astr +='<INPUT TYPE="hidden" NAME="IAm" VALUE="0">' astr +='</TD></TR>' astr +='</TABLE>' astr +='</FORM>' astr +='<BR CLEAR=ALL><H3><BR></H3>' astr +='</BODY></HTML>' ndoc.write(astr) ndoc.close() self.aNoteWin = aPopUp aPopUp.creat = self } function closePopUp() { if ( self.aNoteWin != null ) self.aNoteWin.close() } </SCRIPT> </HEAD> <BODY > <CENTER> <FONT SIZE=5 COLOR='darkred'><B>Example 5</B></FONT>: <FONT SIZE=5 COLOR='darkblue'><B>Running through the History List </B></FONT> </CENTER> <H3><BR><HR><BR></H3> <H3><BR><HR><BR></H3> <CENTER> <FORM NAME='noteForm'> <INPUT TYPE='button' NAME='makeBtn' VALUE='Make Popup' onClick='openPopUp()'> <INPUT TYPE='button' NAME='closeBtn' VALUE='Close Popup'

onclick='closePopUp()'> </FORM> </CENTER> <H3><BR><HR><BR></H3> <H3><BR><HR><BR></H3> <H3><BR><HR SIZE=5 WIDTH=80%><BR></H3> </BODY> </HTML> This pop-up is a variation on our old friend, aNoteWin. It can access its parent's variables through an artificial property of aNoteWin, the creat property, which we carefully write into the child's window as a var, using with the astr += `var creat\n' statement. At the end of the openNote() function, which creates and draws the window, aNoteWin.creat is set to self. This enables you to have ready access to the parent window's variables, functions, and objects.

Security Aspects of JScript Objects


Although it would be useful to retrieve history list items, this functionality has been removed from JScript. Unfortunately, each history list entry contains the entire location, including the search string. If this information could be retrieved, the possibility exists that credit card or other personal information might be gleaned by malicious individ-uals. You may have wondered why there is no windows array. This also does not exist in JScript for security reasons. If it did, a script from one window might reach into another unrelated window and scavenge information from its form elements or its location object. Again, what might be perceived as a limitation in JScript has been imposed to protect you.

The Document Object


The document object encapsulates all JScript objects that correspond to the HTML elements. It is the parent of forms, links, and anchors. These objects occur as arrays and are accessed as document.forms[xx], document.links[xx], and document.anchors[xx], where xx is an array index. The document object also has several other useful properties. It has a property, for example, for all of the standard object colors, such as the background color, text color, and link colors. You cannot change the property of a static closed document, however, so these properties are useful only when building a document. Four properties that are useful in keeping your documents up to date are the location, title, lastModified, and referrer properties. These are used to dynamically write a header or a footer for your documents. Listing 8.9 shows a typical example of how you could use the document object in this way. Note that the properties of the document object are read-only. The attempt to set document.title in this listing will fail. If you want to load this example, you must comment out that line.

Listing 8.9 Writing the Document Header


<HTML> <HEAD> <!- Created 08 Feb 1996 a11:32 PM 11:32 PM --> <TITLE>Writing a Document Header</TITLE> <SCRIPT> document.bgcolor = `linen' document.text = `darkslateblue' document.link = `coral' document.vlink='peach' document.alink='red' document.title='Dynamic Headers' // comment me out document.write(`<TABLE ALIGN=RIGHT WIDTH=300 BORDER=1>') document.write(`<TR><TD>') document.write(`<FONT SIZE=7 COLOR= "navy">') document.write(`<CENTER>' +document.title + `</CENTER>') document.write(`</TD></TR></TABLE>') document.write(`<CENTER><B>') document.write(`<HR>') document.write(`This document was last modified on<BR> <FONT COLOR="red">' + document.lastmodified + `</FONT><BR>') document.write(`Save this URL: <BR><FONT COLOR="red">' + document.location + `</FONT><BR>') document.write(`You arrived here from <BR><FONT COLOR="red">' + document.referrer + `</FONT><BR>') document.write(`<BR><HR><BR>') document.write(`</B></CENTER>') document.write(`') </SCRIPT> </HEAD> <BODY> <H3><BR><HR><BR></H3> <H3><BR><HR SIZE=5 WIDTH=80%><BR></H3> </BODY> </HTML> Forms. You can get input from your users via HTML form elements (sometimes known as widgets). You can have many forms on a page. If they are named (by an HTML NAME directive), you can refer to them by name. You can also refer to a form by its index into the zero-based forms array. Each form can have any one of the standard HTML form elements. These include single-line text, radio, checkbox, hidden, password, reset, and submit. There is also a select widget, which can be either a drop-down list or a plain list, and a textarea widget, which can be used to collect large amounts of text spanning multiple lines. The section on "Using JScript Event Handlers" in Chapter 3, "Events and JScript," talks about the correspondence between HTML form elements, the events that they generate, and their JScript counterparts.

TIP: A script can access only elements that have already been created. They cannot be accessed in a document <HEAD> because the forms and their elements do not yet exist.

Links. Links are the bread and butter of any hypertext system, especially HTML. In JScript, the links array can be canvassed in order to provide a list of links in a document. Links have only one property--the target. The target is not the URL pointed to by the link; rather, it is the window into which that URL will be loaded. Any link is also a location object, so that you can dissect the link in the same way you dissect a location object. Links can have an onClick handler just as buttons do. However, when the onClick handler finishes, the URL specified by the link will be loaded. If you do not want the link to go anywhere, just specify the current URL as its destination. If you want to use a link to execute a function, use HREF= `javascript: myfunc()'. Myfunc() can call a function or contain JScript code. For example, HREF='javascript: self.close()', immediately closes the current window.

CAUTION: A javascript:xxx() call replaces an URL. The browser will try to interpret any return from a function call as if it were an URL. If the browser does not understand the return value, it reloads the current page. When that occurs, any window globals that you set during the xxx() function call will be lost.

Both text and images can be links. You can include both in the same link, if you want, so that clicking either the text or the image will activate the link's events. Because images can be links, you can use them as buttons to call functions if you use javascript:xxx() as the HREF instead of an URL. Unfortunately, because you cannot replace images dynamically, you cannot modify the appearance of the image to simulate a button-down effect. Links can also trap the onMouseOver event. However, it traps this event at the boundaries of the link. What that means is that if you run your mouse pointer over a link, the event will be fired twice: once when you enter the bounding box of the link and once when you leave it. If you use the onMouseOver event to write to the status bar, you find that if you move your mouse too quickly, you miss the status write. This is because it is rapidly replaced by the browser's own response to the event. When you exit, the status written will stay there until you encounter another link. If you want to use the content of your link in a function called from an onMouseOver handler, you can pass the function the keyword this. Links are treated like any other JScript object. Figure 8.3 shows an onMouseOver event being triggered just as the mouse moves over the link.

Figure 8.3 was generated by the code in Listing 8.10, which includes examples of trapping onClick and onMouseOver events from links. It also includes a script that uses the document.links array to write the number of links on the page. Examples of using a javascript:xxx replacement for an URL in a link can be found in Listing 8.4, which uses linked images as buttons.

Listing 8.10 Event Processing for the Link Object


<HTML> <HEAD> <!- Created 09 Feb 1996 a2:45 AM 02:45 AM --> <TITLE>What's Your Link</TITLE> <SCRIPT> function checkOut() { a = (confirm("This file is 10 megs in size. It will take 2 hours to download it. Are your sure you want to do that at this time?")) if (a == true) { alert (`loading file...') } else { alert(`NOT loading file!') } } function enhance(what) { astr = what.href self.status = `Example 4 from this chapter: ` + astr} </SCRIPT> </HEAD> <BODY> <TABLE ALIGN=RIGHT WIDTH=250 BORDER=1> <TR><TD> <FONT SIZE=7 COLOR="darkcorel"> <CENTER>What's Your Link</CENTER> </TD></TR></TABLE> <FONT SIZE=5 >Link Example</FONT><BR> This page demonstrates onClick and mouseOver events for links <HR> <H3><BR><HR><BR></H3> <TABLE ALIGN=LEFT BORDER WIDTH=250>

<TR><TD> <A HREF='C8-4.HTM' onMouseOver='enhance(this)'> <IMG WIDTH=100 HEIGHT=100 VSPACE=2 HSPACE= 2 ALIGN=Left SRC="Images/grkaleid.jpg"> <CENTER><FONT SIZE=5>Enhanced Status</FONT></CENTER></A> </TD></TR></TABLE> This Linked image has an onMouseOver event in its Link tag. This event appears to be fired twice, once when the mouse passes into the boundary of the image and once when it passes out. Move the mouse SLOWLY to see the effect of the event handler. <BR CLEAR ALL> <H3><BR></H3> <TABLE ALIGN=LEFT BORDER WIDTH=250> <TR><TD> <A HREF='C8-3.HTM' onClick='checkOut()'> <IMG WIDTH=32 HEIGHT= 50 VSPACE=2 HSPACE=2 BORDER=2 ALIGN=Left SRC="Images/answer_u.gif"> <CENTER><FONT SIZE=5>File Information</FONT></CENTER></A> </TD></TR></TABLE> This onClick routine asks you if you want to load a very large file. <FONT SIZE=4 COLOR='red'> </FONT> <BR CLEAR ALL> <H3><BR><HR><BR></H3> <H3><BR><HR SIZE=5 WIDTH=80%><BR></H3> </BODY> <SCRIPT> k = document.links.length document.write(`This page has ` + k + ` links. They are: <BR>') </SCRIPT> </HTML> Figure 8.3 MouseOver is fired only when the mouse pointer enters or leaves the linked object. Anchors. Anchors consist of text or images in your document that are marked, usually named, and can be referenced by a link within the same document (known as a local link). The document object has an anchors array, but at this time its use is quite limited. You can find out how many anchors are on the page using the length property.

Dynamic Documents
Dynamic documents created using JScript provide all the functionality of static documents written in HTML. If you can write it in HTML, you can write it on-the-fly in a document script. In fact, you can write your whole document in a script. You have already seen several examples of this, such as Listing 8.8, which creates a small window that can be used to manipulate the history list of the top-

level window. You can also have a script after the </BODY> tag that writes a document footer in a similar fashion.

Restrictions on document.Write
Unfortunately, you cannot change anything on your current page once the document is finished. If you want to write to the current document, you have to open it and write to it via scripts placed at the beginning and end of the document. You can also choose to rewrite the entire document. Using the document.write method is like printing on a dot matrix printer: It is top-down only. This makes it particularly hard to do graphing or other innovative work that requires accurate positioning of objects on the page, because you cannot know in advance where they will end up. You must also be careful when enclosing an HTML statement within a document.write clause. This innocent statement will give you at least one error: Document.write(`<FONT SIZE=5 COLOR='red'>JScript is GREAT!</FONT>') Many HTML parameters need to be quoted, and it is much easier to use single quotes than double quotes. Unfortunately, the write statement above will terminate with the leading quote of `red'. The closing parenthesis of the write statement will not be found, and an error will occur. The problem is easily fixed in this case: Just use double quotes around the word "red". But what do you do if there is a need for a third level of nested quotes? Take this HTML statement for example: <INPUT TYPE='radio' NAME='mycolor' VALUE='red' onClick='Alert("You chose red!")'> This statement already has nested quotes. If you want to enclose this within a document.write() clause, you have two choices:
q

Escape one set of quotes, usually the ones most deeply nested: document.write("<INPUT TYPE='radio' NAME='mycolor' VALUE='red' onClick='Alert(\"You chose red!\")'>")

Put the contents of the deepest quotes into a variable: astr = "You chose red!" document.write("<INPUT TYPE='radio' NAME='mycolor' VALUE='red' onClick='Alert(astr)'>")

If you have more than three levels of quotes, then you must use the second option.

The "Variables and Values" section of Chapter 2, "JScript: The Language," gives the basic rules for string quoting.

Using Nascent Documents


To provide a canvas for you to write on, use the document.open() command. It is often a good idea to precede this with a document.close() command as a safety precaution, in case there is already a document open. You can open or reopen a document in the current window or any window for which you have a reference. Opening a document in that window clears anything that is already there. Once the document is open, you can write to it.

CAUTION: If you issue a document.open() command from within a script in the current page and it is not preceded by a window reference, the current page will be opened. Whatever is on the page is gone! This can be quite a surprise. Don't worry. You can recover the page with a reload, but your users might not know that. Check all document.open() references carefully.

A document is open until you specifically close it or until the browser runs out of things to write on it. When you first open a window, the document associated with that window is also opened. You can then write to it with a header script. Then, the browser writes all of the body, if there is one, and anything it finds in the footer script, if there is one. When it reaches the end of the HTML text, it automatically closes the document. Note that if you open a new window with myNewWin = self. open(`', `NewWin'), you do not have to issue a document.open(). Just start writing on the blank page. We have already noted some items to be careful of in using document.write statements. If you try to write to a document that is not open, nothing will happen. No error will occur--the command will simply fail. You can write anything to a nascent document, including scripts. If you are creating a window from scratch, then you have to write everything. Listings 8.4 and 8.8 earlier in this chapter illustrate this approach.

Troubleshooting I opened a fresh document using document.open(), wrote to it for quite a long time using document.write(), and nothing happened. Where did I go wrong? Document.write() places all of its output into an ASCII stream. Think of it as one big string that exists somewhere in memory. The browser does not get to interpret the stream until you specifically say, "That's all, folks!" with a document.close(). Once you close the document, everything that you have written (hopefully) is rendered

in the browser window. This also means that any script errors will not be noticed until the document is actually closed.

A Page Generated Entirely by JScript


If you examine Listing 8.9, you see that this document is written totally within the header. Let's revisit this document and add a little to it. Suppose that you have a number of images that have the same prefix and differ only in a final numerical suffix. Let us also suppose that these numbers are sequential. With very little JScript, you can dynamically generate the image citations and write them to the page. Listing 8.11 (file C8-6.HTM on the CD-ROM) takes this approach. The for loop is particularly worthy of close examination. It keeps adding citation information to a continuously growing string. When it is finished, it uses one document.write() statement to put the string on the document stream. There are several reasons to use this type of an iterative construct:
q

q q

It is easier to debug. You could use a separate string for each individual citation and pop it up in an alert so that you can check its syntax. It gets rid of some of the nested quote problems. You can save the resulting output string. This is particularly useful if you want actually to write the HTML for the citations as text, rather than have the browser interpret what you write. To do that, you need to replace all < with &lt; and all > with &gt;.

Listing 8.11 c8-6.htm--Generating an Entire Document in JScript


<HTML> <HEAD> <!- Created 08 Feb 1996 a11:32 PM 11:32 PM --> <TITLE>Writing a Document with JScript</TITLE> <SCRIPT> document.bgcolor = `linen' document.text = `darkslateblue' document.link = `coral' document.vlink='peach' document.alink='red' document.write("<TABLE ALIGN=RIGHT WIDTH=350 BORDER=1>") document.write("<TR><TD>") document.write("<FONT SIZE=7 COLOR=indianred>") document.write("<CENTER>" + document.title + "</CENTER>") document.write("</TD></TR></TABLE>") document.write("<BR>") document.write("<LEFT>") document.write("This page is an example of a document written

completely within a script. The reference for each image is generated dynamically") document.write("</LEFT>") document.write("<BR CLEAR ALL>") document.write("<HR>") bstr = `DBLACE' kstr = `' for (i = 1 ; i <= 6 ; i++) { var xstr = bstr + i + `.jpg' kstr += `<IMG SRC=\"Images\/' + xstr + `" ` kstr += `HEIGHT=100 WIDTH=100 VSPACE=5 HSPACE=5 BORDER=2 ALIGN=LEFT>' kstr += `<H3><BR><H3>' kstr += `<CENTER><FONT SIZE=4 COLOR="coral">' + xstr + `</FONT></CENTER>' kstr += `<HR><BR CLEAR ALL>' } document.write(kstr) document.write("<BR><HR><BR>") document.write("This document was last modified on<BR> <FONT COLOR=red><B>" document.write(document.lastModified) document.write("</FONT><BR>") document.write("<BR><HR><BR>") document.write("</B></CENTER>") document.write("") </SCRIPT> </HEAD> <BODY> <H3><BR><HR SIZE=5 WIDTH=80%><BR></H3> </BODY> </HTML>

Dynamically Rewriting Your Page


There are many reasons why you might want to rewrite your page dynamically. You may want to try out various background images and colors, for example. There are two steps to this process: obtaining (or generating) the current information that you will modify, and applying that information to the current page. Because Internet Explorer's current release insists upon sending document.write() calls to a new page, the best one can do is to generate as much information as possible when constructing that new page. Listing 8.12 shows an example of this. It can be easily extended to include a number of different items. In fact, you can build a simple page with it. This code will be found in the CD-ROM file c8-7.htm.

Listing 8.12 c8-7.htm--Using JScript to Dynamically Rewrite a Document


<HTML> <HEAD> <!- Created 08 Feb 1996 a6:10 PM 06:10 PM --> <TITLE>Dynamic Modification of Documents</TITLE> <SCRIPT> function createArray(n) { this.length = n return this } var parms = new createArray(6) function { parms[1] parms[2] parms[3] parms[4] parms[5] reloadMe() = document.forms[0].aname.value = document.forms[0].mytext.value = document.forms[0].mylink.value += document.forms[0].myvlink.value += document.forms[0].myimage.value

var astr astr = `<BODY BACKGROUND = "Images/' + parms[5] + `" ` astr += `TEXT="'+ parms[2] + `" ` astr += `LINK="'+ parms[3] + `" ` astr += `VLINK="'+ parms[4] + `" ` astr += `ALINK="red" ` astr += `>\n' document.write(astr) document.write(`<TABLE ALIGN=RIGHT WIDTH=350 BORDER=1>') document.write(`<TR><TD>') document.write(`<FONT SIZE=7 COLOR= "indianred">') document.write(`<CENTER>' + document.title + `</CENTER>') document.write(`</TD></TR></TABLE>') document.write(`<LEFT><B>') document.write(`This page is an example of dynamically revised by a header script which acts on user\' choices.') document.write(`</B></LEFT>') document.write(`<BR CLEAR ALL>') document.write(`<HR>') astr ='<CENTER><FONT SIZE=7 COLOR="' + parms[3] + `"><B> ` astr += parms[1] + `</B></FONT></CENTER>' document.write(astr)

document.write(`<HR><BR>') document.close(); } function clearUp() { self.location = self.location.pathname } function doTC(what) { what.form.mytext.value = what.value } function doLC(what) { what.form.mylink.value = what.value } function doVC(what) { what.form.myvlink.value = what.value } function doImage(what) { document.forms[0].myimage.value = `DBLACE' + what + `.jpg' } function doname(what) { what.form.aname.value = what.value } </SCRIPT> </HEAD> <BODY> <CENTER> <FORM NAME=nameForm> Enter your first name here:<BR> <INPUT TYPE=text NAME=myname SIZE= 20 onChange='doname(this)'><H3><BR></H3> <CENTER> <TABLE ALIGN=LEFT WIDTH=100 BORDER CELLPADDING=5> <TR ALIGN=LEFT><TD> <CENTER><B>Text</B></CENTER>

<INPUT TYPE="RADIO" (this)'>white<BR> <INPUT TYPE="RADIO" (this)'>yellow<BR> <INPUT TYPE="RADIO" (this)'>navy<BR> <INPUT TYPE="RADIO" (this)'>blue<BR> <INPUT TYPE="RADIO" (this)'>orange<BR> <INPUT TYPE="RADIO" (this)'>red<BR> <INPUT TYPE="RADIO" (this)'>black<BR> </TD></TR></TABLE>

NAME="tc" VALUE='white' ONCLICK='doTC NAME="tc" VALUE='yellow' ONCLICK='doTC NAME="tc" VALUE='navy' ONCLICK='doTC NAME="tc" VALUE='blue' ONCLICK='doTC NAME="tc" VALUE='orange' ONCLICK='doTC NAME="tc" VALUE='red' ONCLICK='doTC NAME="tc" VALUE='black' ONCLICK='doTC

<TABLE ALIGN=LEFT WIDTH=100 BORDER CELLPADDING=5> <TR ALIGN=LEFT><TD> <CENTER><B>Link</B></CENTER> <INPUT TYPE="RADIO" NAME="lc" VALUE='white' ONCLICK='doLC (this)'>white<BR> <INPUT TYPE="RADIO" NAME="lc" VALUE='yellow' ONCLICK='doLC (this)'>yellow<BR> <INPUT TYPE="RADIO" NAME="lc" VALUE='navy' ONCLICK='doLC (this)'>navy<BR> <INPUT TYPE="RADIO" NAME="lc" VALUE='blue' ONCLICK='doLC (this)'>blue<BR> <INPUT TYPE="RADIO" NAME="lc" VALUE='orange' ONCLICK='doLC (this)'>orange<BR> <INPUT TYPE="RADIO" NAME="lc" VALUE='red' ONCLICK='doLC (this)'>red<BR> <INPUT TYPE="RADIO" NAME="lc" VALUE='black' ONCLICK='doLC (this)'>black<BR> </TD></TR></TABLE> <TABLE ALIGN=LEFT WIDTH=100 BORDER CELLPADDING=5> <TR ALIGN=LEFT><TD> <CENTER><B>VLink</B></CENTER> <INPUT TYPE="RADIO" NAME="vc" VALUE='white' ONCLICK='doVC (this)'>white<BR> <INPUT TYPE="RADIO" NAME="vc" VALUE='yellow' ONCLICK='doVC (this)'>yellow<BR> <INPUT TYPE="RADIO" NAME="vc" VALUE='navy' ONCLICK='doVC (this)'>navy<BR> <INPUT TYPE="RADIO" NAME="vc" VALUE='blue' ONCLICK='doVC (this)'>blue<BR>

<INPUT TYPE="RADIO" NAME="vc" VALUE='orange' ONCLICK='doVC (this)'>orange<BR> <INPUT TYPE="RADIO" NAME="vc" VALUE='red' ONCLICK='doVC (this)'>red<BR> <INPUT TYPE="RADIO" NAME="vc" VALUE='black' ONCLICK='doVC (this)'>black<BR> </TD></TR></TABLE> </CENTER> <BR CLEAR ALL> <HR> <CENTER><FONT SIZE=4>Click on the image that you want for a background.</FONT></CENTER> <H3><BR></H3> <A HREF='javascript:doImage(1)'> <IMG WIDTH=100 HEIGHT= 100 VSPACE=5 HSPACE=5 BORDER=2 ALIGN=Left SRC="Images/DBLACE1.jpg"></A> <A HREF='javascript:doImage(2)'> <IMG WIDTH=100 HEIGHT= 100 VSPACE=5 HSPACE=5 BORDER=2 ALIGN=Left SRC="Images/DBLACE2.jpg"></A> <A HREF='javascript:doImage(3)'> <IMG WIDTH=100 HEIGHT= 100 VSPACE=5 HSPACE=5 BORDER=2 ALIGN=Left SRC="Images/DBLACE3.jpg"></A> <A HREF='javascript:doImage(4)'> <IMG WIDTH=100 HEIGHT= 100 VSPACE=5 HSPACE=5 BORDER=2 ALIGN=Left SRC="Images/DBLACE4.jpg"></A> <A HREF='javascript:doImage(5)'> <IMG WIDTH=100 HEIGHT= 100 VSPACE=5 HSPACE=5 BORDER=2 ALIGN=Left SRC="Images/DBLACE5.jpg"></A> <BR CLEAR ALL> <HR> </CENTER> <TABLE ALIGN= RIGHT WIDTH=300><TR ALIGN=RIGHT><TD> Name: <INPUT TYPE=text NAME=aname><BR> My Image: <INPUT TYPE=text NAME=myimage><BR> My Text: <INPUT TYPE=text NAME=mytext><BR> My Link: <INPUT TYPE=text NAME=mylink><BR> My VLink: <INPUT TYPE=text NAME=myvlink><BR> </TD></TR></TABLE> <INPUT TYPE=button NAME=reloadBtn VALUE='Rewrite Page' onClick='reloadMe()'> <INPUT TYPE=button NAME=clearBtn VALUE= `Clear' onClick='clearUp()'>

<INPUT TYPE=hidden NAME=hideFld> </FORM> <HR> <H3><BR><HR><BR></H3> <H3><BR><HR SIZE=5 WIDTH=80%><BR></H3> </BODY> </HTML> Figure 8.4 shows the result of loading this page. The page starts out in the default IE colors. It gives the user the opportunity to select text and link colors, and a background tile. The user is in the process of selecting a tile. Figure 8.4 A dynamically rewritten page stores information for use in the next rewrite operation. This script does several things that are worth noting, as follows:
q

It creates a global array named parms. It does not bother to initialize the array, because the program knows which parts of the array it is going to use later. It has a simple routine named reloadMe() to gather all of the form elements and write them to the location object. Its header script acts on the information provided by the user to dynamically reconstruct the page.

Figure 8.5 shows all the choices being placed in the summary form as the user clicks and enters text. Figure 8.6 shows the browser window after it has been rewritten dynamically to use the colors and tiles chosen by the user. Figure 8.5 Dynamic documents can modify their own appearance under user control. You can write to any page that appears in your window hierarchy. You cannot write to a page that is not a part of that hierarchy. Consequently, a parent can write to a child window and a child can write to its parent. If you want a parent window to write to a newly created child window, then you need to keep a handle to that window. The window.open() method returns such a handle; you should store this value as a global variable. It can then be used subsequently to access the child. If you do not use a global variable, you will not be able to access the child window from any function other than the one that created it. Figure 8.6 Dynamic documents can rewrite their own background.

The openNote() Script Revisited

Let's examine the very first complete example in this chapter (Listing 8.3) again now that you have more knowledge and experience. The parent window has two buttons, one to open the window and one to close it. These buttons call the parent window's functions, openNote() and closeNote (), respectively. The parent stores the handle to the openNote window in the global variable, aNoteWin. The responsibilities of the open routine are as follows:
q q

It defines the appearance of the window using the open(...) parameters. It writes the script of the window, including any event handle functions that are called by window objects and any initialization for the window. It writes the HTML for all of the objects in the window. In this case, the objects are a table with two buttons and the note text. The Close button includes the onClick handler that calls the closeNote() function of the child window.

The open routine also exemplifies a common and useful time-saving practice, known as aliasing. The full hierarchical representation of aNoteWin's document (self.aNoteWin.document) is collected in the short and easy-to-write variable known as ndoc. Finally, it is worth pointing out the utility of having the child window's Close button in the parent window, especially if the child window is small. The open() method will not create a second window of the same name, although it can do some updating if you make a second open() call with different parameters. If you click the Make Note button and nothing happens, it is possible that you did not get rid of the last window you made. Murphy's Law dictates that the forgotten child will be at the very bottom of the eight other large windows on your screen. Being able to close the window from the parent is a great time-saver and an excellent debugging tool.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Chapter 15 Visual Effects


q

Visual Effects r Creating Dynamic Framesets s The javascript: Protocol s Empty Frames s Content Variables versus Functions r A Simple Color Alternator r A Better Color Alternator s Color Objects s The Alternator Object s Events and the EventQueue s Scheduling Multiple Events r A Color Fader r A Scrolling Marquee r The Static Object r Animating Images r Generating Images s The XBM Format s Representing an XBM Image s XBM Drawing Methods s Displaying Generated Images

Visual Effects
Some of the main topics in this chapter are
q q q q

Create a color alternator Build an event scheduler Write a color fader Make a scrolling marquee

Generate XBM images The flat, static Web page may not yet be a thing of the past. But as the number of pages on the Web spirals into the tens of millions, new creative approaches are required both to catch viewers' attention and to hold their interest. Web page designers may now choose from a growing array of tools to lend visual impact to their creations.

In this chapter, you'll see how JScript can be used to create several useful visual effects, including alternating color schemes, fades, scrolling marquees, and dynamic graphics. Unlike effects created using other tools, JScript effects load quickly as part of your document, and can start even before a page is completely loaded.

Creating Dynamic Framesets


Before we get started, let's take a look at the frameset environment we'll use to create visual effects. Because Internet Explorer 3.0 does not provide a way to update a document directly once it has been written to the screen, all of the effects we create here require that we write a new document to the screen for each step in an animation, marquee, or other effect. Rather than load each successive document from the server (which would be much too slow), we'll generate our documents on-the-fly and then slap them into frames. Listing 15.1 shows the skeleton frameset that we'll develop in the examples that follow.

Listing 15.1 Skeleton Frameset


<html> <head> <title>Visual Effects</title> <script language="JavaScript"> <!-- begin script var emptyFrame = `<html></html>'; function headFrame () { return `<html><body bgcolor="#FFFFFF" text="#000000">' + `<h1 align="center">Visual Effects</h1>' + `</body></html>'; } function initialize () { self.head.location = "javascript:parent.headFrame()"; } // end script --> </script> <frameset rows="52,*" onLoad="initialize()"> <frame name="head" src="javascript:parent.emptyFrame" marginwidth=1 marginheight=1 scrolling="no" noresize> <frame name="body" src="javascript:parent.emptyFrame"> </frameset> <noframes> <h2 align="center">JScript or JavaScript-enabled browser required</h2> </noframes> </html>

Some of the syntax and techniques used here are a bit different from what you've seen so far. But it's all perfectly legal. Let's take a minute to dissect this skeleton script.

The javascript: Protocol


You've often seen http: or ftp: at the beginning of an URL. This is the protocol: It tells the browser which protocol handler to use to retrieve the object referred to after the colon. The javascript: protocol is really no different; it simply instructs the browser to let JScript retrieve the object. But rather than initiate communication with another server, the JScript handler returns the value of the variable or function cited after the colon. The value returned should be HTML or some other MIME type the browser knows how to display. When using a javascript: URL, keep in mind that the reference after the colon is specified from the perspective of the receiving frame. In our example, from the point of view of the head frame, the headFrame() function is in the parent frame.

Empty Frames
Sometimes it's desirable to leave a frame blank initially and load the contents later. For instance, the value of the frame may depend on user input or the result of a lengthy calculation or process. You could load an empty document from the server, but that wastes a server access. It's faster and easier to use the javascript: protocol to load the empty document internally. The <HTML></HTML> pair used in our emptyFrame variable isn't strictly necessary under IE --an empty string works just as well. But other JScript-enabled browsers may not be as forgiving. You may be wondering why we need to use an empty frame at all in this example, at least for the head frame, as we could load it directly. In fact, it sometimes happens that frames loaded using the javascript: protocol align incorrectly if they are loaded directly from a FRAME tag. So, instead, we must load an empty document in the FRAME tag and then load the intended document from the onLoad handler for the frameset. You might also be tempted to simply leave off the SRC= attribute. However, frames that do not have an initial location specified cannot be updated with a new location.

NOTE: You may have seen frameset documents that use about:blank to specify an empty frame. This is a Netscape-specific construction and should be avoided. Internet Explorer does not support the about: construction.

Content Variables versus Functions

In our skeleton frameset, emptyFrame is a variable containing HTML, while headFrame() is a function that returns HTML. Either method can be used. In general, use variables if the content will not change. Use functions to return dynamic content.

A Simple Color Alternator


One of the easiest visual effects to create is a color alternator, which switches between two color schemes in a frame. This effect is best used in small frames containing large, bold headlines. It should not generally be used with smaller, more detailed text, as it will make such text difficult to read while the effect is in progress. It would also be wise to use this effect in moderation--a brief burst of alternating colors can be very effective when your page first loads, when making a transition to a new topic, or to underscore a point. However, continuous flashing quickly becomes annoying to the viewer. (Remember the fate of the BLINK tag!) Let's start with a simple, direct example. Building on our skeleton frameset, In Listing 15.2, we modify the headFrame() function to return one of two BODY tags, depending on the state of a variable called headColor.

Listing 15.2 The Modified headFrame() Function


var headColor = "white"; function headFrame () { return `<html>' + ((headColor == "white") ? `<body bgcolor="#FFFFFF" text="#000000">' : `<body bgcolor="#000000" text="#FFFFFF">') + `<h1 align="center">Visual Effects</h1>' + `</body></html>'; } In Listing 15.3, we create a function called setHead() that uses JScript's setTimeout() function to create a timer loop. We'll update the head frame six times, alternating colors each time.

Listing 15.3 The setHead() Function Alternates Colors


var headLoops = 6; function setHead () { if (headColor == "white") headColor = "black"; else headColor = "white"; if (--headLoops > 0) setTimeout (`setHead()', 100); self.head.location = "javascript:parent.headFrame()";

} Finally, we'll call setHead() in our initialize() function. function initialize() { setHead(); } When our example page is loaded, the head frame will alternate rapidly between white-on-black and black-on-white. The entire effect lasts less than one second. The output is shown in Figure 15.1.

NOTE: The absolute update rate which one can get with timer events will vary from platform to platform. On some systems, it might be as few as three per second.

Figure 15.1 The heading frame alternates between black-on-white (shown here) and white-on-black (shown in Figure 15.2). Figure 15.2 Here is an example of white-on-black. Listing 15.4 shows the complete code for this example. This example will be found as file c15-1.htm on the CD-ROM.

Listing 15.4 The Simple Color Alternator


<html> <head> <title>Visual Effects</title> <script language="JavaScript"> <!-- begin script var emptyFrame = `<html></html>'; var headColor = "white"; function headFrame () { return `<html>' + ((headColor == "white") ? `<body bgcolor="#FFFFFF" text="#000000">' : `<body bgcolor="#000000" text="#FFFFFF">') + `<h1 align="center">Visual Effects</h1>' + `</body></html>'; } var headLoops = 6;

function setHead () { if (headColor == "white") headColor = "black"; else headColor = "white"; if (--headLoops > 0) setTimeout (`setHead()', 125); self.head.location = "javascript:parent.headFrame()"; } function initialize () { setHead(); } // end script --> </script> <frameset rows="52,*" onLoad="initialize()"> <frame name="head" src="javascript:parent.emptyFrame" marginwidth=1 marginheight=1 scrolling="no" noresize> <frame name="body" src="javascript:parent.emptyFrame"> </frameset> <noframes> <h2 align="center">JScript or JavaScript-enabled browser required</h2> </noframes> </html>

A Better Color Alternator


Our first color alternator works fine if you plan to use the effect only once with one set of colors in a single frame. But if you plan to use this effect more extensively, you'll end up duplicating a lot of code. In this section, we'll develop a generalized version of the color alternator that offers greater flexibility and can easily be reused. We'll take an object-oriented, component-based approach in this example. This might initially appear to be overkill, but as you will see, the components we create here provide the foundation for more complex effects.

Color Objects
Let's start by defining a Color object and some related functions. As you know, colors in HTML (and JScript) are represented by hexadecimal triplets of the form RRGGBB, in which each two-digit hexadecimal code represents the red, green, or blue component of a color. Values range between 00 and FF hex, corresponding to zero to 255 decimal. Our Color object constructor, shown in Listing 15.5, accepts a hexadecimal string, but stores the individual components as numbers, which are easier to manipulate.

Listing 15.5 The Color Object Constructor


var hexchars = `0123456789ABCDEF'; function fromHex (str) { var high = str.charAt(0); var low = str.charAt(1); return (16 * hexchars.indexOf(high)) + hexchars.indexOf(low); } function toHex (num) { return hexchars.charAt(num >> 4) + hexchars.charAt(num & 0xF); } function Color (str) { this.red = fromHex(str.substring(0,2)); this.green = fromHex(str.substring(2,4)); this.blue = fromHex(str.substring(4,6)); this.toString = ColorString; return this; } function ColorString () { return toHex(this.red) + toHex(this.green) + toHex(this.blue); } As you might expect, the fromHex() and toHex() functions convert between numeric and hexadecimal values. Note that these functions will work with values only in the range 00 to FF hex (zero to 255 decimal). By the way, it should be possible to write the fromHex() function more compactly, as function fromHex (str) { return (16 * hexchars.indexOf(str.charAt(0))) + hexchars.indexOf(str.charAt(1)); } The ColorString() function is defined as the Color object's toString() method. This function converts the color back to an RGB triplet, and is automatically invoked any time a Color object is used in a context that requires a string.

TIP: Any JScript object can be given a toString() method, which is automatically called whenever an object needs to be converted to a string value.

Let's use the Color constructor to define a few colors:

var var var var var

black = new Color ("000000"); white = new Color ("FFFFFF"); blue = new Color ("0000FF"); magenta = new Color ("FF00FF"); yellow = new Color ("FFFF00");

Now that we've got our colors in a convenient form, let's define an object to contain all the colors in use by a document at a given moment. We'll call this the BodyColor object. Its constructor is shown in Listing 15.6.

Listing 15.6 The BodyColor Object Constructor


function BodyColor (bgColor,fgColor,linkColor,vlinkColor, alinkColor) { this.bgColor = bgColor; this.fgColor = fgColor; this.linkColor = linkColor; this.vlinkColor = vlinkColor; this.alinkColor = alinkColor; this.toString = BodyColorString; return this; } function BodyColorString () { return `<body' + ((this.bgColor == null) ? `' : ` bgcolor="#' + this.bgColor + `"`) + ((this.fgColor == null) ? `' : ` text="#' + this.fgColor + `"`) + ((this.linkColor == null) ? `' : ` link="#' + this.linkColor + `"`) + ((this.vlinkColor == null) ? `' : ` vlink="#' + this.vlinkColor + `"`) + ((this.alinkColor == null) ? `' : ` alink="#' + this.alinkColor + `"`) + `>'; } The BodyColor() constructor accepts up to five Color objects as parameters, one for each HTML body color attribute. The colors are specified in the order of generally accepted importance; trailing colors can be omitted if they will not be used. So, for instance, if a document does not contain any links, the last three parameters can safely be left off. Like the Color constructor, the BodyColor constructor includes a toString() method: the BodyColorString() function. In this case, a complete BODY tag is returned, including any color attributes specified. Note that the individual Color objects are used directly in the construction of the BODY tag string.

Because they are used in a context requiring a string, the Color object's toString() method will automatically be called to translate these into hexadecimal triplet strings! Let's define a few BodyColor objects. Because we won't be using any links in this example, we'll omit the three link parameters: var var var var var blackOnWhite = new BodyColor (white, black); whiteOnBlack = new BodyColor (black, white); blueOnWhite = new BodyColor (white, blue); magentaOnYellow = new BodyColor (yellow, magenta); yellowOnBlue = new BodyColor (blue, yellow);

In this case, we've used colors we defined previously. Because we're likely to reuse these colors, it was worthwhile to assign them to named variables. But suppose we wanted to use a color only once in a specific BodyColor object. It seems--and is--inefficient to define a variable just to hold an object we're going to use immediately: var weirdOne = new Color ("123ABC"); var oddBody = new BodyColor (weirdOne, yellow); Instead, we can invoke the Color constructor directly from the BodyColor constructor parameter list without ever assigning a name to the color: var oddBody = new BodyColor (new Color ("123ABC"), yellow);

TIP: When creating an object that is referred to by name only once, you can invoke its constructor in the parameter list of the function or method that will use it instead of assigning it to a named variable.

The Alternator Object


Our next step is to create an object that generates HTML that alternates between two BodyColor specifications. We'll call this the Alternator object. Its constructor is shown in Listing 15.7.

Listing 15.7 The Alternator Object Constructor


function Alternator (bodyA, bodyB, text) { this.bodyA = bodyA; this.bodyB = bodyB; this.currentBody = "A"; this.text = text;

this.toString = AlternatorString; return this; } function AlternatorString () { var str = "<html>"; with (this) { if (currentBody == "A") { str += bodyA; currentBody = "B"; } else { str += bodyB; currentBody = "A"; } str += text + `</body></html>'; } return str; } The Alternator() constructor accepts two BodyColor objects plus a string containing whatever is to appear between <BODY> and </BODY>. In theory, the text string can be arbitrarily long, but 4K seems to be the maximum usable length on most platforms. In our examples, this string will be much shorter. The currentBody variable indicates which BodyColor object is used to generate the BODY tag. This is switched by the toString() method, AlternatorString(), each time it is invoked. Let's create an Alternator object now. We'll use the same text that appeared in the head frame of our simple alternator example: var flashyText = new Alternator (blackOnWhite, whiteOnBlack, `<h1 align="center">Visual Effects</h1>'); Each time flashyText is referenced, it will alternate between black-on-white and white-on-black output. For example, suppose we loaded flashyText into three frames consecutively: self.frameA.location = "javascript:parent.flashyText"; self.frameB.location = "javascript:parent.flashyText"; self.frameC.location = "javascript:parent.flashyText";

Events and the EventQueue


All that's left is to write our flashyText object to the screen at regular intervals. To do this, we'll create an object called an Event, which--in this context--is an action that is scheduled to take place at a particular time. We can define our Event object so that a separate event was required for each

write to the screen, but this would require a lot of extra coding. Instead, we'll build a looping mechanism into our Event object because most of the effects we create in this chapter involve multiple writes to the screen. Listing 15.8 shows the Event constructor.

Listing 15.8 The Event Object Constructor


function Event (start, loops, delay, action) { this.start = start * 1000; this.next = this.start; this.loops = loops; this.loopsRemaining = loops; this.delay = delay * 1000; this.action = action; return this; } The Event constructor takes the start time for the event (relative to the time the program is launched or the time the EventQueue is started), the number of times (loops) to execute the event, the delay between each execution, and the action to be performed for the event. The start time and delay are specified in seconds, but are converted to milliseconds for internal use. The action can be any valid JScript statement enclosed in quotes. (This is similar to the way you specify an action for JScript's setTimeout() function.) The following is the Event constructor for our flashyText object: var flashEvent = new Event (0, 10, 0.1, `self.head.location="javascript:parent.flashyText"'); We will start the event at time zero, that is, as soon as the EventQueue is started. We'll loop ten times with each loop one-tenth of a second apart. The action for the event is to load the flashyText object into the head frame. We've defined an Event, but it's still just sitting there. This is where the EventQueue object comes in. The EventQueue contains a list of Event objects to be acted upon. It handles the scheduling and looping of events and executes the associated actions. Listing 15.9 shows the EventQueue constructor and related functions. This is a fairly complex bit of code; we won't go through it line-by-line, but we'll cover the key parameters and methods below.

Listing 15.9 The EventQueue Object Constructor


function EventQueue (name, delay, loopAfter, loops, stopAfter) { this.active = true; this.name = name; this.delay = delay * 1000; this.loopAfter = loopAfter * 1000;

this.loops = loops; this.loopsRemaining = loops; this.stopAfter = stopAfter * 1000; this.event = new Object; this.start = new Date (); this.loopStart = new Date(); this.eventID = 0; this.addEvent = AddEvent; this.processEvents = ProcessEvents; this.startQueue = StartQueue; this.stopQueue = StopQueue; return this; } function AddEvent (event) { this.event[this.eventID++] = event; } function StartQueue () { with (this) { active = true; start = new Date(); loopStart = new Date(); loopsRemaining = loops; setTimeout (name + ".processEvents()", this.delay); } } function StopQueue () { this.active = false; } function ProcessEvents () { with (this) { if (!active) return; var now = new Date(); if (now.getTime() - start.getTime() >= stopAfter) { active = false; return; } var elapsed = now.getTime() - loopStart.getTime(); if (elapsed >= loopAfter) { if (--loopsRemaining <= 0) { active = false; return; } loopStart = new Date(); elapsed = now.getTime() - loopStart.getTime(); for (var i in event) if (event[i] != null) {

event[i].next = event[i].start; event[i].loopsRemaining = event[i].loops; } } for (var i in event) if (event[i] != null) if (event[i].next <= elapsed) if (event[i].loopsRemaining-- > 0) { event[i].next = elapsed + event[i].delay; eval (event[i].action); } setTimeout (this.name + ".processEvents()", this.delay); } } The first parameter to the EventQueue constructor is the queue name. This must be the same as the variable name to which the EventQueue object is assigned. (This is a bit of a kludge, but is required for the event processor to make setTimeout() calls to itself.) Next, the delay parameter specifies how often the events in the queue are checked. This is important because it determines the maximum rate of actions for all events in the queue. If you specify a queue delay of 0.10 seconds, but an event delay of 0.05 seconds, the event will be executed only every 0.10 seconds. Therefore, the delay should be set to the smallest value required by your events. Values smaller than 0.05 seconds are not recommended. The loopAfter parameter specifies the number of seconds after which the entire EventQueue starts over. This enables entire complex sequences of events to be repeated. The loops parameter specifies the number of times the entire EventQueue repeats. Set this to zero if you do not want the queue to repeat. The stopAfter parameter indicates the number of seconds after which the queue stops processing events, regardless of the number of loops remaining. Set this to an arbitrarily chosen high number, such as 99999, if you do not want the queue to stop after any particular length of time. Once the EventQueue has been defined, you can then use the addEvent() method to add events to the queue. Let's create an event queue and add our flashEvent object to it. var evq = new EventQueue ("evq", 0.1, 30, 10, 99999); evq.addEvent (flashEvent); Our event queue will check for events every 0.1 seconds. It will start over every 30 seconds, repeating 10 times. If, for some reason, it is still active after 99999 seconds, it will stop processing. The final step is to start the queue. We'll do this in our initialize() function, which is the

onLoad handler for our frameset. function initialize () { evq.startQueue(); } That's it! We're in business! After creating numerous functions and scores of lines of code, we now have exactly what we started with in our first, "simple" example. But wait--there's more.

Scheduling Multiple Events


As noted at the beginning of this section, this somewhat complex approach to generating the Alternator effect isn't really necessary if you are going to use a single effect only once in your program. But the advantages quickly multiply when you create complex effects or sequences of events. Each new event requires just a few lines of code, as Listing 15.10 demonstrates.

Listing 15.10 Adding New Alternator Events


var dance1 = new Alternator (yellowOnBlue, magentaOnYellow, `<h1 align="center">Dancing...</h1>'); var inthe1 = new Alternator (magentaOnYellow, yellowOnBlue, `<h1 align="center">...in the...</h1>'); var streets1 = new Alternator (whiteOnBlack, yellowOnBlue, `<h1 align="center">...streets!</h1>'); var d1e = new Event (0, 10, .1, `self.f1.location="javascript:parent.dance1"'); var i1e = new Event (3, 10, .1, `self.f1.location="javascript:parent.inthe1"'); var s1e = new Event (6, 10, .1, `self.f1.location="javascript:parent.streets1"'); evq.addEvent(d1e); evq.addEvent(i1e); evq.addEvent(s1e); Listing 15.11 shows the complete code for the improved alternator with an expanded example. The output is shown in Figure 15.3. In the sections that follow, you'll see how you can easily build on our event model to create even more interesting effects. This code will be found in the file c15alt.htm.

Listing 15.11 c15alt.htm--Complete Code for the Improved Alternator


<html> <head> <title>Visual Effects</title> <script language="JavaScript">

<!-- begin script var emptyFrame = `<html></html>'; var hexchars = `0123456789ABCDEF'; function fromHex (str) { var high = str.charAt(0); var low = str.charAt(1); return (16 * hexchars.indexOf(high)) + hexchars.indexOf(low); } function toHex (num) { return hexchars.charAt(num >> 4) + hexchars.charAt(num & 0xF); } function Color (str) { this.red = fromHex(str.substring(0,2)); this.green = fromHex(str.substring(2,4)); this.blue = fromHex(str.substring(4,6)); this.toString = ColorString; return this; } function ColorString () { return toHex(this.red) + toHex(this.green) + toHex(this.blue); } function BodyColor (bgColor,fgColor,linkColor,vlinkColor, alinkColor) { this.bgColor = bgColor; this.fgColor = fgColor; this.linkColor = linkColor; this.vlinkColor = vlinkColor; this.alinkColor = alinkColor; this.toString = BodyColorString; return this; } function BodyColorString () { return `<body' + ((this.bgColor == null) ? `' : ` bgcolor="#' + this.bgColor + `"`) + ((this.fgColor == null) ? `' : ` text="#' + this.fgColor + `"`) + ((this.linkColor == null) ? `' : ` link="#' + this.linkColor + `"`) + ((this.vlinkColor == null) ? `' : ` vlink="#' + this.vlinkColor + `"`) + ((this.alinkColor == null) ? `' : ` alink="#' + this.alinkColor + `"`) + `>'; } function Alternator (bodyA, bodyB, text) { this.bodyA = bodyA;

this.bodyB = bodyB; this.currentBody = "A"; this.text = text; this.toString = AlternatorString; return this; } function AlternatorString () { var str = "<html>"; with (this) { if (currentBody == "A") { str += bodyA; currentBody = "B"; } else { str += bodyB; currentBody = "A"; } str += text + `</body></html>'; } return str; } function Event (start, loops, delay, action) { this.start = start * 1000; this.next = this.start; this.loops = loops; this.loopsRemaining = loops; this.delay = delay * 1000; this.action = action; return this; } function EventQueue (name, delay, loopAfter, loops, stopAfter) { this.active = true; this.name = name; this.delay = delay * 1000; this.loopAfter = loopAfter * 1000; this.loops = loops; this.loopsRemaining = loops; this.stopAfter = stopAfter * 1000; this.event = new Object; this.start = new Date (); this.loopStart = new Date(); this.eventID = 0; this.addEvent = AddEvent; this.processEvents = ProcessEvents; this.startQueue = StartQueue; this.stopQueue = StopQueue;

return this; } function AddEvent (event) { this.event[this.eventID++] = event; } function StartQueue () { with (this) { active = true; start = new Date(); loopStart = new Date(); loopsRemaining = loops; setTimeout (name + ".processEvents()", this.delay); } } function StopQueue () { this.active = false; } function ProcessEvents () { with (this) { if (!active) return; var now = new Date(); if (now.getTime() - start.getTime() >= stopAfter) { active = false; return; } var elapsed = now.getTime() - loopStart.getTime(); if (elapsed >= loopAfter) { if (--loopsRemaining <= 0) { active = false; return; } loopStart = new Date(); elapsed = now.getTime() - loopStart.getTime(); for (var i in event) if (event[i] != null) { event[i].next = event[i].start; event[i].loopsRemaining = event[i].loops; } } for (var i in event) if (event[i] != null) if (event[i].next <= elapsed) if (event[i].loopsRemaining-- > 0) { event[i].next = elapsed + event[i].delay; eval (event[i].action); }

setTimeout (this.name + ".processEvents()", this.delay); } } var black = new Color ("000000"); var white = new Color ("FFFFFF"); var blue = new Color ("0000FF"); var magenta = new Color ("FF00FF"); var yellow = new Color ("FFFF00"); var var var var var blackOnWhite = new BodyColor (white, black); whiteOnBlack = new BodyColor (black, white); blueOnWhite = new BodyColor (white, blue); yellowOnBlue = new BodyColor (blue, yellow); magentaOnYellow = new BodyColor (yellow, magenta);

var flashyText = new Alternator (blackOnWhite, whiteOnBlack, `<h1 align="center">Visual Effects</h1>'); var dance1 = new Alternator (yellowOnBlue, magentaOnYellow, `<h1 align="center">Dancing...</h1>'); var dance2 = new Alternator (whiteOnBlack, yellowOnBlue, `<h1 align="center">Dancing...</h1>'); var dance3 = new Alternator (new BodyColor(black,yellow), magentaOnYellow, `<h1 align="center">Dancing...</h1>'); var inthe1 = new Alternator (magentaOnYellow, yellowOnBlue, `<h1 align="center">...in the...</h1>'); var inthe2 = new Alternator (blackOnWhite, whiteOnBlack, `<h1 align="center">...in the...</h1>'); var inthe3 = new Alternator (yellowOnBlue, blueOnWhite, `<h1 align="center">...in the...</h1>'); var streets1 = new Alternator (whiteOnBlack, yellowOnBlue, `<h1 align="center">...streets!</h1>'); var streets2 = new Alternator (blueOnWhite, magentaOnYellow, `<h1 align="center">...streets!</h1>'); var streets3 = new Alternator (yellowOnBlue, blackOnWhite, `<h1 align="center">...streets!</h1>'); var flashEvent = new Event (0, 10, 0.1, `self.head.location="javascript:parent.flashyText"'); var d1e = new Event (0, 10, .1, `self.f1.location="javascript:parent.dance1"'); var d2e = new Event (5, 10, .1, `self.f2.location="javascript:parent.dance2"'); var d3e = new Event (10, 10, .1, `self.f3.location="javascript:parent.dance3"'); var i1e = new Event (3, 10, .1, `self.f1.location="javascript:parent.inthe1"');

var i2e = new Event (8, 10, .1, `self.f2.location="javascript:parent.inthe2"'); var i3e = new Event (13, 10, .1, `self.f3.location="javascript:parent.inthe3"'); var s1e = new Event (6, 10, .1, `self.f1.location="javascript:parent.streets1"'); var s2e = new Event (11, 10, .1, `self.f2.location="javascript:parent.streets2"'); var s3e = new Event (16, 10, .1, `self.f3.location="javascript:parent.streets3"'); var evq = new EventQueue ("evq", 0.1, 20, 10, 60); evq.addEvent (flashEvent); evq.addEvent(d1e); evq.addEvent(i1e); evq.addEvent(s1e); evq.addEvent(d2e); evq.addEvent(i2e); evq.addEvent(s2e); evq.addEvent(d3e); evq.addEvent(i3e); evq.addEvent(s3e); function initialize () { evq.startQueue(); } // end script --> </script> <frameset rows="52,52,52,52,*" onLoad="initialize()"> <frame name="head" src="javascript:parent.emptyFrame" marginwidth=1 marginheight=1 scrolling="no" noresize> <frame name="f1" src="javascript:parent.emptyFrame" marginwidth=1 marginheight=1 scrolling="no" noresize> <frame name="f2" src="javascript:parent.emptyFrame" marginwidth=1 marginheight=1 scrolling="no" noresize> <frame name="f3" src="javascript:parent.emptyFrame" marginwidth=1 marginheight=1 scrolling="no" noresize> <frame name="body" src="javascript:parent.emptyFrame"> </frameset> <noframes> <h2 align="center">JScript or JavaScript-enabled browser required</h2> </noframes> </html> Figure 15.3

Alternating text events are scheduled in four frames.

A Color Fader
Like the Alternator effect, the Fader effect involves the transition from one color scheme to another. But instead of jumping abruptly between colors, the Fader displays a series of intermediate shades, creating the illusion of a smooth transition. Although the Alternator effect is noisy and jarring, the Fader effect is calm, serene, even solemn. In particular, a slow fade up from (or down to) black can lend a somber, serious tone to the message being conveyed. Or the Fader can be used to create wild, psychedelic effects--whichever best suits your purpose. By now, it should come as no surprise that we'll start by creating a new object type. But before we create the Fader object itself, we need to create a special object that calculates an intermediate color value between two Color objects. I'll call this the IntColor object. Its constructor is shown in Listing 15.12.

Listing 15.12 The IntColor Object Constructor


function IntColor (start, end, step, steps) { this.red = Math.round(start.red+(((end.red-start.red)/(steps-1))*step)); this.green = Math.round(start.green+(((end.green-start.green)/(steps-1))*step)); this.blue = Math.round(start.blue+(((end.blue-start.blue)/(steps-1))*step)); this.toString = ColorString; return this; } The IntColor() constructor takes two Color objects--start and end--plus the number of steps between the start and end colors and the current step. The resultant object is identical to a Color object and can be used as such. It may be convenient to think of IntColor() as just another constructor for a Color object. Now that we have a way to calculate intermediate colors, we can create our Fader object. Listing 15.13 shows its constructor.

Listing 15.13 The Fader Object Constructor


function Fader (bodyA, bodyB, steps, text) { this.bodyA = bodyA; this.bodyB = bodyB; this.step = 0; this.steps = steps;

this.text = text; this.toString = FaderString; return this; } function FaderString () { var intBody = new BodyColor(); with (this) { if (bodyA.bgColor != null && bodyB.bgColor != null) intBody.bgColor = new IntColor (bodyA.bgColor, bodyB.bgColor, step, steps); if (bodyA.fgColor != null && bodyB.fgColor != null) intBody.fgColor = new IntColor (bodyA.fgColor, bodyB.fgColor, step, steps); if (bodyA.linkColor != null && bodyB.linkColor != null) intBody.linkColor = new IntColor (bodyA.linkColor, bodyB.linkColor, step, steps); if (bodyA.vlinkColor != null && bodyB.vlinkColor != null) intBody.vlinkColor = new IntColor (bodyA.vlinkColor, bodyB.vlinkColor, step, steps); if (bodyA.alinkColor != null && bodyB.alinkColor != null) intBody.alinkColor = new IntColor (bodyA.alinkColor, bodyB.alinkColor, step, steps); step++; if (step >= steps) step = 0; } return `<html>' + intBody + this.text + `</body></html>'; } The Fader object itself is similar in construction to the Alternator object. The Fader() constructor takes a beginning BodyColor object (bodyA), an ending BodyColor object (bodyB), and a text string containing the HTML and text to be displayed. In addition, the Fader() constructor takes the number of steps to be used in the transition from the beginning colors to the ending colors. The toString() method, FaderString(), is a bit more complex than its Alternator counterpart. It creates a temporary BodyColor object, and populates it with IntColor objects for each color attribute that is present in both the beginning and ending BodyColor objects. It then increments the current step. When all steps have been completed, it resets the current step to zero, so the object can be reused. It returns the specified text, along with an embedded BODY tag generated from the temporary BodyColor object. It may have occurred to you that a Fader object with steps set to 2 performs exactly the same function as an Alternator object. However, the code is a little longer and involves more processing.

TIP: If you are using both Alternator and Fader objects, you can use a Fader object with two steps in place of an Alternator object and omit the alternator code to save space.

A Fader object is defined in much the same way as an Alternator object, as shown in Listing 15.14. The complete source code for the Fader effect will be found in the CD-ROM file c15fade.htm.

Listing 15.14 Using the Fader Object


var fadingText = new Fader (yellowOnBlue, magentaOnYellow, 10, `<h1 align="center">Visual Effects</h1>'); var evq = new EventQueue ("evq", 0.1, 20, 10, 60); evq.addEvent (new Event (0, 10, 0.1, `self.head.location="javascript:parent.fadingText"')); Notice that instead of creating a named variable for our Fader event, we defined it in the parameter list for the addEvent() method. If you have a lot of events, making up names for them can be a chore--not to mention a source of confusion. When creating events for Fader objects, it's important to remember that the number of loops specified for the event should normally be the same as the number of steps in the fade. If you specify a smaller number of loops, you'll get an incomplete fade; specify a larger number, and the fade will start over with the initial color.

A Scrolling Marquee
By now, you've probably seen dozens of pages with a scrolling text ticker down at the bottom in the status area. Besides being hard to read, these tend to block out the usual status messages associated with cursor actions. The Java applet and ActiveX marquees and tickers are much better, but they take a while to load and won't run on all platforms. However, you can enjoy the best of both worlds by creating a JScript marquee that's both readable and quick to load. Ideally, our marquee should be able to display text in a variety of fonts, sizes, and colors, in any combination. So, before we define the Marquee object itself, let's create some text-handling objects that will help us do just that. The Text and Block object constructors are shown in Listing 15.15.

Listing 15.15 The Text and Block Object Constructors


function Text (text, size, format, color) { this.text = text;

this.length = text.length; this.size = size; this.format = format; this.color = color; this.toString = TextString; this.substring = TextString; return this; } function TextString (start, end) { with (this) { if (TextString.arguments.length < 2 || start >= length) start = 0; if (TextString.arguments.length < 2 || end > length) end = length; var str = text.substring(start,end); if (format != null) { if (format.indexOf("b") >= 0) str = str.bold(); if (format.indexOf("i") >= 0) str = str.italics(); if (format.indexOf("f") >= 0) str = str.fixed(); } if (size != null) str = str.fontsize(size); if (color != null) { var colorstr = color.toString(); str = str.fontcolor(colorstr); } } return str; } function Block () { var argv = Block.arguments; var argc = argv.length; var length = 0; for (var i = 0; i < argc; i++) { length += argv[i].length; this[i] = argv[i]; } this.length = length; this.entries = argc; this.toString = BlockString; this.substring = BlockString; return this; } function BlockString (start, end) { with (this) { if (BlockString.arguments.length < 2 || start >= length) start = 0; if (BlockString.arguments.length < 2 || end > length) end = length; } var str = "";

var segstart = 0; var segend = 0; for (var i = 0; i < this.entries; i++) { segend = segstart + this[i].length; if (segend > start) str += this[i].substring(Math.max(start,segstart)-segstart, Math.min(end,segend)-segstart); segstart += this[i].length; if (segstart >= end) break; } return str; } The Text object is used to contain a string, along with font, size, and color information. If you look closely, you'll see that the Text object has some interesting properties, both figuratively and literally. The Text object is designed to mimic JScript strings, but with some important differences. The Text object has a length property, for instance, and a substring() method. But while the length property returns the length of the text itself, the substring() method returns the requested substring plus the HTML tags required to render the substring in the desired font, size, and color. Why is this important? Because the Marquee object must display segments of text to produce its scrolling effect; so to maintain proper formatting, it needs to be able to retrieve substrings as small as a single character with all their HTML attributes intact. The Text() constructor takes a text string, and, optionally, a font size, a Color object, and a format string. The format string can contain the lowercase letters b, i, or f, or any combination of the three, which stand for bold, italic, and fixed, respectively. The Color object specifies the foreground color to be used when displaying the text.

NOTE: The font size must be passed as a string (e.g., "7"), rather than a number, when specified as a parameter to the Text() constructor.

The Block object is used to combine two or more Text objects, JScript strings, or even other Block objects in any combination. Like the Text object, the Block object mimics JScript string behavior. A call to its substring() method might return portions of several of its constituent objects, with all their HTML formatting intact. The Block() constructor accepts any number of Text, string, or Block objects. These can be considered to be logically concatenated in the order specified in the argument list.

Listing 15.16 shows an example of using Text and Block objects.

Listing 15.16 Using Text and Block Objects


var var var var var var t1 t2 t3 t4 b1 b2 = = = = = = new new new new new new Text ("When shall ", "5", "", blue); Text ("we three ", "6", "fb", red); Text ("meet again, ", "5", "bfi", yellow); Text ("or in rain? ", "6", "ib", red); Block (t3, "In thunder, lightning, ", t4); Block (t1, t2, b1);

A call to b2.substring(5,25) would then return the following: <FONT COLOR="#0000FF"><FONT SIZE="5">shall </FONT></FONT> <FONT COLOR="#FF0000"><FONT SIZE="6"><TT><B>we three </B></TT></ FONT></FONT> <FONT COLOR="#FFFF00"><FONT SIZE="5"><I><B>meet </B></I></FONT></ FONT> Your Using Text and Block objects, you can create marquees in a wide variety of styles. Now let's take a look at the Marquee object itself. Listing 15.17 shows its constructor.

Listing 15.17 The Marquee Object Constructor


function Marquee (body, text, maxlength, step) { this.body = body; this.text = text; this.length = text.length; this.maxlength = maxlength; this.step = step; this.offset = 0; this.toString = MarqueeString; return this; } function MarqueeString () { with (this) { var endstr = offset + maxlength; var remstr = 0; if (endstr > text.length) { remstr = endstr - text.length; endstr = text.length; } var str = nbsp(text.substring(offset,endstr) +

((remstr == 0) ? "" : text.substring(0,remstr))); offset += step; if (offset >= text.length) offset = 0; else if (offset < 0) offset = text.length - 1; } return `<html>' + this.body + `<table border=0 width=100% height=100%><tr>' + `<td align="center" valign="center">' + str + `</td></tr></table></ body></html>'; } function nbsp (strin) { var strout = ""; var intag = false; var len = strin.length; for(var i=0, j=0; i < len; i++) { var ch = strin.charAt(i); if (ch == "<") intag = true; else if (ch == ">") intag = false; else if (ch == " " && !intag) { strout += strin.substring(j,i) + "&nbsp"; j = i + 1; } } return strout + strin.substring(j,len); } The body parameter to the Marquee() constructor accepts a BodyColor object. This object determines the overall color scheme for the marquee. The text parameter can be a Block object, a Text object, or a JScript string object. The text produced by this object will be scrolled across the screen to create the marquee effect. Any colors embedded in this object will override the foreground color specified in the body parameter for the corresponding section of text. The maxlength parameter is the maximum length of the text returned by the Marquee object, not counting HTML formatting tags. You will need to experiment with this a bit to get the right width. A good starting point is to use the width of the marquee frame divided by ten. So for a 400-pixel-wide window, start with 40 and then adjust as necessary. It's okay to specify a length slightly larger than the frame width, but if you specify a much longer length, it will slow down processing and increase memory usage. The step parameter specifies the number of characters the marquee will scroll each time it is

invoked. You will generally want to set this to 1 or 2, or, to scroll backwards, -1 or -2. Combined with the delay time defined for the Marquee event, the step parameter determines how fast the Marquee scrolls across the screen. The toString() method, MarqueeString(), uses a table to center the text vertically and horizontally within the frame. (Depending on how you use the Alternator and Fader objects, you may want to modify their toString() methods to do this as well.) Note that if you use a combination of large and small fonts in your marquee, the text may "wobble" vertically during the transition from one size to another. The nbsp() function is used to replace all space characters with nonbreaking spaces (&nbsp). This enables you to include consecutive spaces (normally ignored by HTML) in your text. It also prevents the scrolling text from breaking into two or more lines when the font is small enough or the marquee window large enough that this would otherwise occur. In Listing 15.18, we create a Marquee, using the opening lines from Shakespeare's Macbeth for our text.

Listing 15.18 Using the Marquee Object


var mbScene = new Block ( new Text ("When shall we three meet again, ", "5", "b", red), new Text ("In thunder, lightning, or in rain? ", "6", "bf", blue), new Text ("When the hurlyburly\'s done, ", "5", "ib", yellow), new Text ("When the battle\'s lost and won. ", "6", "bfi", magenta), new Text ("That will be ere the set of sun. ", "6", "fb", red), "................" ); var mbMarquee = new Marquee (whiteOnBlack, mbScene, 50, 2); var evq = new EventQueue ("evq", 0.1, 120, 5, 600); evq.addEvent (new Event (0, mbMarquee.length * 3, 0.125, `self.f1.location = "javascript:parent.mbMarquee"')); There are several points to note in this example. First, rather than define a separate named variable for each Text object, I created them in the parameter list for the Block constructor. Again, this is usually preferable to cluttering your program with a lot of variables that are referenced only once. Next, notice that I escaped the apostrophes in the text using the \ character. It's sometimes easy to forget to do this when you're working with real-world text in JScript applications. The line of dots at the end of the Block acts as a separator between the end of the text and the beginning when the marquee wraps around. In this particular case, it would have been better to use a Text object with a larger font size because the rest of the text in the block uses larger fonts. But the point to keep in mind is that you can use plain strings in Block objects if you want to.

Finally, when creating the Event for the marquee, the number of loops is specified as a multiple of the length of the Marquee object. This is much easier than counting all the characters in the Block object manually! The complete code for this example is included on the accompanying CD-ROM in the file c15marq.htm. Its output is shown in Figure 15.4. Figure 15.4 A scrolling marquee can include multiple font styles, colors, and sizes.

The Static Object


In some cases, you may just want to put some text in a frame at a particular time. This isn't really an effect, per se, but it would be convenient to have an object similar to the rest of our objects for this purpose. The Static object fills this need. Its constructor is shown in Listing 15.19.

Listing 15.19 The Static Object Constructor


function Static (body, text) { this.body = body; this.text = text; this.toString = StaticString; return this; } function StaticString () { return `<html><body>' + this.body + this.text + `</body></html>'; } The Static() constructor takes a BodyColor object and a text string, which may contain HTML. You could also use a Text object or a Block object for the text parameter. The following is an example of using the Static object: var beHere = new Static (blackOnWhite, `<h1 align="center">Be Here Now</h1>'); var evq = new EventQueue ("evq", 0.1, 120, 5, 600); evq.addEvent (new Event (12, 1, 10, `self.f1.location = "javascript:parent.beHere"'));

Animating Images
The best way to animate images using JScript is not to. Internet Explorer 3.0 supports GIF89a multipart images, which contain built-in timing and looping instructions. These load faster and run more smoothly than animation created using JScript and can be placed anywhere on the page (whereas JScript animations currently require their own frame). A number of inexpensive shareware utilities are available for creating GIF animation, the best known of which is probably GIF

Construction Set by Alchemy Mindworks. All that said, there may be cases when you want or need to create an animation using JScript. In particular, you may want to do so when you're creating images on-the-fly, a subject that will be treated in depth in the next section. Before we create our Animator object, we'll need an object to hold information about individual images. Listing 15.20 shows the constructor for the Image object.

Listing 15.20 The Image Object Constructor


function Image (url, width, height) { this.url = url; this.width = width; this.height = height; return this; } The URL parameter to the Image() constructor must be a fully specified URL; relative URLs won't work within the framework we've developed because the default protocol is always assumed to be javascript:. The width and height parameters are required, but don't necessarily have to be accurate: Internet Explorer will attempt to automatically scale images to the width and height specified. Now, let's take a look at our Animator object. Its constructor is shown in Listing 15.21.

Listing 15.21 The Animator Object Constructor


function Animator (name, body) { var argv = Animator.arguments; var argc = argv.length; for (var i = 2; i < argc; i++) this[i-2] = argv[i]; this.name = name; this.body = body; this.images = argc - 2; this.image = 0; this.ready = "y"; this.toString = AnimatorString; return this; } function AnimatorString () { var bodystr = this.body.toString(); var bodystr = bodystr.substring(0, bodystr.length - 1) + ` onLoad="parent.' + this.name + `.ready=\'y\'">';

var str = `<html>' + bodystr + `<table border=0 width=100% height=100%><tr><td align="center" valign="center">' + `<img src="' + this[this.image].url + `" width=' + this[this.image]. width + ` height=' + this[this.image].height + `></td></table></body></ html>'; this.image++; if (this.image >= this.images) this.image = 0; this.ready = "n"; return str; } The Animator() constructor takes a name parameter, which must be the same as the variable name assigned to the Animator object. This is followed by a BodyColor object, and any number of Image objects. You will generally want to create your Image objects in the parameter list for the Animator() constructor. Unlike the Color, Text, and other objects we've used in our effects so far, images are not immediately available when we want to put them on the screen--they are usually loaded from a server. And there's no reliable way of guessing how long that will take. If you try to display them on a fixed timetable, most likely none of them would get a chance to load completely: The next image you try to display would clobber the one currently loading, and the browser would start loading it again from scratch the next time it was called for. The only way to get around this is to let each image load completely before displaying the next image. The Animator object does this by including an onLoad handler in the BODY tag for each image it writes to the screen. When the Animator object's toString() method, AnimatorString(), generates a new frame, it sets the ready flag in the object to n, meaning that the Animator is not ready to display a new frame. Once the image has loaded completely, the onLoad handler is called and sets the ready flag back to y. (This is the reason you need to specify the name of the Animator object: so the onLoad handler knows which object to update.) The last part of this trick falls to the Event object we create for the Animator. You may recall that an Event's action can be any valid JScript statement, so simply include an if statement in the action to test whether the Animator is ready before updating the frame. Listing 15.22 shows an example of using the Animator. The source code for this example will be found on the CD-ROM in the file c15anim.htm.

Listing 15.22 Using the Animator Object


var anim = new Animator ("anim", blackOnWhite, new Image ("http://www.hidaho.com/colorcenter/img/logo1.gif", 32, 32),

new Image ("http://www.hidaho.com/colorcenter/img/logo2.gif", 32, 32), new Image ("http://www.hidaho.com/colorcenter/img/logo3.gif", 32, 32), new Image ("http://www.hidaho.com/colorcenter/img/logo4.gif", 32, 32), new Image ("http://www.hidaho.com/colorcenter/img/logo5.gif", 32, 32), new Image ("http://www.hidaho.com/colorcenter/img/logo6.gif", 32, 32), new Image ("http://www.hidaho.com/colorcenter/img/logo7.gif", 32, 32), new Image ("http://www.hidaho.com/colorcenter/img/logo8.gif", 32, 32) ); var evq = new EventQueue ("evq", 0.1, 120, 5, 600); evq.addEvent (new Event (0, 60, 0.1, `if (anim.ready=="y") self.f1.location="javascript:parent.anim"'));

Generating Images
Loading images from a server has its limitations. Apart from the amount of time this can take-especially over a slow connection--you generally have a fixed set of images to work with (unless you generate images on the server using a CGI program). There are times when it is useful to create images on-the-fly, perhaps in response to user input or to create a dynamic animation. JScript offers two solutions. The first is to use single-pixel GIF files to construct images. Because IE automatically scales images to the specified width and height, you can create rectangles of various dimensions from a 1x1 GIF image of a particular color. This technique is especially useful for creating dynamic bar charts; but beyond that, its applications are very limited. I won't cover this technique here, but I encourage you to experiment with it on your own. The second solution is to generate XBM-format images. You may not have heard of these before, but you've probably seen them. They're often used as icons in server directory Listings. You are most likely to see one when downloading a file via FTP. The greatest drawback to XBM images is that they're monochromatic--in other words, black-andwhite, though IE renders them as black-and-gray. But this is also something of an advantage to us because they can be represented internally as a string of bits, one per pixel, on or off. This also makes manipulating them fairly straightforward and not too costly in terms of processor cycles--an important consideration when working with an interpreted language, such as JScript. Also important to us, the XBM file's native format is ASCII text, which can be represented using JScript strings.

The XBM Format

An XBM image consists of a header specifying its width and height in pixels and a string of hexadecimal byte codes. As shown in Listing 15.23, it looks a lot like something you'd find in a Clanguage source file.

Listing 15.23 An XBM Image File Header


#define xbm_width 32 #define xbm_height 32 static char xbm_bits[] = { 0xFF,0x02,0x88,0x25,0x3C,0xB4,0x11,0xDB, ... }; The names xbm_width, xbm_height, and xbm_bits are not part of the specification. We chose these because they are descriptive, but the names could be any valid C-style identifiers--it's the format that's important. Each byte code is a bitmap corresponding to eight pixels in a row of pixels. The first byte code represents the upper-left-most eight pixels in an image. Bits are processed from left to right until the specified width is reached. The next set of bits then defines the next row of pixels, and so on, until the entire image is drawn.

Representing an XBM Image


We'll represent the XBM bits internally as JScript numbers. Because JScript uses 32-bit integers, it makes sense to store 32 XBM bits in each JScript number. However, it turns out that the high-order sign bit can't be set on some platforms, so we'll use 16-bit numbers instead. This wastes some space, but the math is much easier if we stick with powers of 2. Our XBM images will be made up of two type of objects: the xbmRow object, which contains an array of 16-bit numbers, and the xbmImage object, which contains an array of xbmRow objects. These objects both contain additional information used in manipulating the image and in translating it to ASCII text for display. Listing 15.24 shows their constructors.

Listing 15.24 The xbmRow and xbmImage Object Constructors


function xbmRow (parent, columns, initialValue) { this.redraw = true; this.text = null; this.parent = parent; this.col = new Object(); for (var i = 0; i < columns; i++) this.col[i] = initialValue; this.toString = xbmRowString;

return this; } function xbmImage (width, height, initialValue) { this.width = (width+15)>>4; this.pixelWidth = this.width<<4; this.height = height; this.head = "#define xbm_width " + (this.pixelWidth) + "\n#define xbm_height " + this.height + "\nstatic char xbm_bits[] = {\n"; this.initialValue = ((initialValue == null) ? 0 : initialValue); this.negative = false; this.row = new Object(); for (var i = 0; i < height; i++) this.row[i] = new xbmRow(this, this.width, this.initialValue); this.drawPoint = xbmDrawPoint; this.drawLine = xbmDrawLine; this.drawRect = xbmDrawRect; this.drawFilledRect = xbmDrawFilledRect; this.drawCircle = xbmDrawCircle; this.drawFilledCircle = xbmDrawFilledCircle; this.reverse = xbmReverse; this.clear = xbmClear; this.partition = xbmPartitionString; this.toString = xbmString; return this; } The xbmImage() constructor takes the width and height of the image, in pixels, as parameters. An optional initial value can also be specified--if supplied; this will create a pattern of vertical lines in the image. Otherwise, a zero is assumed, which results in a blank image. The xbmImage() constructor calls the xbmRow() constructor to create each row in the image. xbmRow() should be considered an internal function. You don't need to call it directly. Both xbmImage and xbmRow have toString() methods: xbmImageString() and xbmRowString(), respectively. These create the ASCII representation of the XBM image when it's time to display it. A third method, xbmPartitionString(), optimizes the string-building process, which would otherwise consume an excessive amount of memory. These are shown in Listing 15.25.

Listing 15.25 The xbmImage toString() Methods


function xbmRowString () { if (this.redraw) { this.redraw = false;

this.text = ""; for (var i = 0; i < this.parent.width; i++) { var pixels = this.col[i]; if (this.parent.negative) pixels ^= 0xFFFF; var buf = "0x" + hexchars.charAt((pixels>>4)&0xF) + hexchars.charAt(pixels&0xF) + ",0x" + hexchars.charAt((pixels>>12)&0xF) + hexchars.charAt((pixels>>8)&0xF) + ","; this.text += buf; } } return this.text; } function xbmPartitionString (left,right) { if (left == right) { var str = this.row[left].toString(); if (left == 0) str = this.head + str; else if (left == this.height - 1) str += "};\n"; return str; } var mid = (left+right)>>1; return this.partition(left,mid) + this.partition(mid+1,right); } function xbmString () { return this.partition(0,this.height - 1); }

XBM Drawing Methods


The foundation of our XBM drawing capability is the drawPoint() method, xbmDrawPoint (), shown in Listing 15.26. As all of our XBM drawing methods, the drawPoint() method doesn't actually draw anything on the screen. Instead, it updates the internal state of the xbmImage object to indicate that the specified point needs to be drawn.

Listing 15.26 The xbmDrawPoint() Function


function xbmDrawPoint (x,y) { if (x < 0 || x >= this.pixelWidth || y < 0 || y >= this.height) return; this.row[y].col[x>>4] |= 1<<(x&0xF); this.row[y].redraw = true;

} The drawPoint() method takes the x and y coordinates of the point to be drawn. These are specified relative to the upper-left corner of the image, which is point (0,0). The y coordinate is used as an index into the array of xbmRow objects. The high-order bits of the x coordinate are used to compute an index into the array of JScript numbers representing the row. The low-order bits are then used to calculate the bit offset for the desired pixel coordinate, which is turned on. Let's create an xbmImage object and draw a point: var picture = new xbmImage (64,64); picture.drawPoint(10,15); Drawing points can be useful for creating fine detail within an image, but it would take a lot of drawPoint() calls to create a useful image. Fortunately, we have some more powerful drawing methods at our disposal. The drawLine() method, xbmDrawLine(), shown in Listing 15.27, draws a line between two points by making a series of calls to drawPoint(). It takes two pairs of coordinates, (x1,y1) and (x2,y2), as parameters. The algorithm is reasonably efficient, at least in the context of an interpreted language. The drawLine() method forms the basis of our rectangle-drawing algorithms, shown in Listing 15.28.

Listing 15.27 The xbmDrawLine() Function


function xbmDrawLine (x1,y1,x2,y2) { var x,y,e,temp; var dx = Math.abs(x1-x2); var dy = Math.abs(y1-y2); if ((dx >= dy && x1 > x2) || (dy > dx && y1 > y2)) { temp = x2; x2 = x1; x1 = temp; temp = y2; y2 = y1; y1 = temp; } if (dx >= dy) { e = (y2-y1)/((dx == 0) ? 1 : dx); for (x = x1, y = y1; x <= x2; x++, y += e) this.drawPoint(x,Math.round(y)); } else {

e = (x2-x1)/dy; for (y = y1, x = x1; y <= y2; y++, x += e) this.drawPoint(Math.round(x),y); } }

Listing 15.28 Rectangle Drawing Functions


function xbmDrawRect (x1,y1,x2,y2) { this.drawLine (x1,y1,x2,y1); this.drawLine (x1,y1,x1,y2); this.drawLine (x1,y2,x2,y2); this.drawLine (x2,y1,x2,y2); } function xbmDrawFilledRect (x1,y1,x2,y2) { var x,temp; if (x1 > x2) { temp = x2; x2 = x1; x1 = temp; temp = y2; y2 = y1; y1 = temp; } for (x = x1; x <= x2; x++) this.drawLine(x,y1,x,y2); } The drawRect() method, xbmDrawRect(), draws a hollow rectangle, given two opposing corner coordinate pairs, (x1,y1) and (xy,y2). The drawFilledRect() method, xbmDrawFilledRect(), draws a filled rectangle, as you probably guessed. Let's draw some lines and rectangles. This example code will be found in the CD-ROM file c15xbm. htm. Note this only modifies the contents of an xbmImage object named picture--it does not actually draw anything. The technique for actual drawing is described below. var picture = new xbmImage (64,64); picture.drawLine (0,0,63,63); picture.drawRect (32,0,63,32); picture.drawFilledRect (0,32,32,63); Our last two drawing methods, shown in Listing 15.29, draw hollow and filled circles.

Listing 15.29 Circle Drawing Functions

function xbmDrawCircle (x,y,radius) { for (var a=0, b=1; a < b; a++) { b = Math.round(Math.sqrt(Math.pow(radius,2)-Math.pow(a,2))); this.drawPoint(x+a,y+b); this.drawPoint(x+a,y-b); this.drawPoint(x-a,y+b); this.drawPoint(x-a,y-b); this.drawPoint(x+b,y+a); this.drawPoint(x+b,y-a); this.drawPoint(x-b,y+a); this.drawPoint(x-b,y-a); } } function xbmDrawFilledCircle (x,y,radius) { for (var a=0, b=1; a < b; a++) { b = Math.round(Math.sqrt(Math.pow(radius,2)-Math.pow(a,2))); this.drawLine(x+a,y+b,x+a,y-b); this.drawLine(x-a,y+b,x-a,y-b); this.drawLine(x+b,y+a,x+b,y-a); this.drawLine(x-b,y+a,x-b,y-a); } } The drawCircle() method, xbmDrawCircle(), and the drawFilledCircle() method, xbmDrawFilledCircle(), take the coordinates of the center point of the circle plus the radius. These methods take advantage of the fact that it's necessary only to compute the points for a single octant (one-eighth) of a circle. They compute these points relative to an origin of (0,0), and then translate them to the eight octants relative to the x and y coordinates. Because the drawPoint() method automatically "clips" any points that don't lie within the image area, we can draw circles that only partially intersect our image, using the following code: var picture = new xbmImage (64,64); picture.drawCircle (32,32,20); // completely within image

Displaying Generated Images


A generated xbmImage object can be displayed in much the same way that an ordinary image would be displayed, except that it has a javascript: URL. Listing 15.30 shows an example of using the Static object to supply the surrounding HTML.

Listing 15.30 Displaying an xbmImage Object


picture = new xbmImage (64,64); picture.drawLine (0,0,63,63);

picture.drawLine (0,63,63,0); var pictureFrame = new Static (whiteOnBlack, `<img src="javascript:parent.picture" width=64 height=64>'); self.frameA.location = "javascript:parent.pictureFrame"; Note, however, that once an xbmImage has been displayed, any subsequent changes to it will not be displayed when you redraw the frame. Internet Explorer assumes that images of a given name don't change, so it uses its cached copy after the first draw. The workaround is to assign the xbmImage object to an object with a different name and then redraw it. You can animate a series of xbmImages using the Animator object we created earlier. Just specify the javascript: URL of the image in the Image object.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Chapter 17 Using Frames and Cookies


q

Using Frames and Cookies r Parameter Specification and Data Storage s Storing Parameters and Other Data s Storing Persistent Data in Cookies r Frames and JScript s Specifying Frames in HTML s Building a Frameset s Frames Within Frames s Replaced with Another Frameset s Examples of Interframe Communication s Writing a New Document into a Frame s Building a JScript Function Library in a Frameholder

Using Frames and Cookies


q q q

Store information in cookies Build frame-sets and commun- icate between them Manage a JScript function library Create nested framesets

One of the tremendous advantages of hypertext is its ability to link together many pieces of information in a nonlinear fashion. Rather than having to read a book one page at a time, you can leap from one link to the next as you explore different topics and their interconnections. However, sometimes this easy access to information can have unfortunate and cumbersome side effects. One such side effect occurs when you find yourself moving back and forth between a small set of pages, over and over again. This happens because of a problem with presentation: The information you want is scattered over more than one page. If you are reading a tutorial, for example, you may find that you are revisiting the Table of Contents page with dreary repetitiveness. You can avoid this by having multiple browser windows open at the same time, but this often takes up too much of your display. This chapter focuses on the emerging HTML frames technology, which addresses this issue of presentation. Both Microsoft's Internet Explorer version 3.0 and the Netscape Navigator browser enable you to split a single browser window into multiple, independent subwindows, each containing its own URL. These subwindows are known as frames. We will explore frames technology and its

close relationship to JScript in some detail. To do this, we must first address the related topic of data storage. Sophisticated applications often require both data presentation and data storage/management capabilities. Unfortunately, information or parameter storage is particularly difficult. Both Microsoft and Netscape provide a persistent means of storage via Cookies. We explore this method in the first section of this chapter, and then subsequently illustrate how such data can then be used to format a page on-the-fly.

Parameter Specification and Data Storage


Because Microsoft is extremely security-conscious, storing or loading data is difficult--even between document reloads. Chapter 8, "Dynamic HTML and IE Objects," briefly described one method of storing simple data between document reloads via a string saved in location.search. This special location.search property is often referred to as the command line. A script can retrieve this string and redraw itself based on information in the string. This approach is limited in the current release of Internet Explorer, however, so we will discuss the more permanent storage option offered by Cookies. The "JScript Object Hierarchy" section of Chapter 8, "Dynamic HTML and IE Objects," discusses the location object and its various properties, including the search property.

Storing Parameters and Other Data


If you have a lot of data, you might appreciate having it accumulated and stored for you. You can use a submit widget or form.submit() to have the browser collect all of your data, encode it, and store it in the command line. Another possibility is to store data in dynamic arrays in a window or, better, in the frameset document. Unfortunately, this, too, is unstable. If you have database-like data, it must all be handcoded into the document that will host it, although you could use an HTML builder or other programming tool to automatically create the HTML document. The only possibility that offers any permanence is Cookies. Cookies are lines in a file that the browser enables you to write to disk. This file will be stored in the Cookies folder on a Windows machine, or in a file called COOKIES on a Macintosh. Cookies are limited in size and number. Nevertheless, Cookies are extremely useful. They are frequently used in the same way as a Windows . INI file, a Macintosh Preferences file, or a UNIX .RC file. The next subsection examines the Cookie approach.

Storing Persistent Data in Cookies


The only method you can use to store variables between invocations of Internet Explorer v3 is the Cookie approach. This is also the only approach that works with windows in different hierarchies. It should also be noted that the specification for the Cookie storage format is still a draft, so the

approach described in this section should be used with caution. Cookies were originally designed to enable a server to save information on the client's disk. When the client contacted that same host at a later time, the previously saved Cookie would be sent back to the server. Cookies are therefore useful if a browser connection is interrupted and you want to pick up where you left off. They are also useful in case the server crashes and later wants to pick up where it left off. Cookies are now available for general use in JScript. Cookies have the following five parameters: NAME=VALUE expires=DATE path=PATH domain=DOMAIN_NAME secure Only the first one, which is a familiar NAME=VALUE pair, is required. All of the others are optional. However, if you do not save an expiration date, the Cookie automatically expires when you close Internet Explorer --not something you want to happen if you want to keep information from session to session. The various parameters are separated by semicolons. If you create a Cookie with the same name and path as a Cookie already in existence, the new one overwrites the existing one. Although servers can write named Cookies one at a time, JScript cannot. You can set an individual named Cookie with the statement, document.Cookie='Cookiename=xxxx', but when you retrieve document.Cookie, you get a string consisting of all of the Cookies. Currently, the only way to retrieve an individual Cookie is to search through the entire set of Cookies obtained from document.Cookie. Consequently, it helps to add a prefix or suffix to the names of your Cookies with little-used characters. This makes them easy to find with indexOf(). Let's examine each of the Cookie parameters in turn. As stated, the NAME=VALUE parameter is an associative pair. This means that it lends itself nicely to being stored in arrays and placed in form elements. This is the only required element of the Cookie. The expires=DATE parameter is used to describe the expiration date for the Cookie. As defined by the draft standard Cookie specification, the date format must be "Wdy, DD-Mon-YY HH:MM:SS GMT" with the separators exactly as given. If you do not want persistent data between browser invocations, leave out this expiration date. If you want your Cookie never to expire, give it a date several years in the future. The path=PATH parameter is used to limit the search path of a server that can see your Cookies. This is analogous to specifying a document BASE in an HTML document. If you use a slash (/), then everything in the domain can use your Cookies. The domain=DOMAIN_NAME parameter is useful only if the server is setting the Cookie or, if for some reason, you want to generate a Cookie that is available to the server. If the server generated the Cookie, then the default domain is the domain name of the server that generated it. Finally, the parameter, secure, indicates that the Cookie should be sent only if there is a secure client/server relationship. Listing 17.1 shows the Cookie versions of the routines for saving and restoring persistent

information. This code will be found on the CD-ROM in the file C17-1.htm. The information goes to, and comes from, the document Cookie. These routines have been liberally modified from the original versions, which were written by Bill Dortch and placed in the public domain.

Listing 17.1 c17-1.htm--Saving and Restoring Document Cookie Information


function fixSep(what) // escapes any semicolons you might have in your data { n=0 while ( n >= 0 ) { n = what.indexOf(`;',n) if (n < 0) return what else { what = what.substring(0,n) + escape(`;') + what.substring(n+1,what.length) n++ } } return what } function toCookie() { document.Cookie = `' nform = document.data for (i=0 ; i<nform.length; i++) { expr = makeYearExpDate(1) astr = fixSep(nform.elements[i].value) astr= nform.elements[i].name + `=' + astr + `;expires=' + expr + `;path=/' document.Cookie=astr } } function makeYearExpDate(yr) { var expire = new Date(); expire.setTime (expire.getTime() + ((yr*365) * 24 * 60 * 60 * 1000)); expire = expire.toGMTString()

return expire } function getCookieAt(n) { e = document.Cookie.indexOf (";", n); if (e == (-1)) e = document.Cookie.length rstr= unescape(document.Cookie.substring(n,e)) return rstr } function fromCookie() //restores summary fields from Cookie { nform = document.data astr = document.Cookie cl = astr.length counter=0 for (i = 0 ; i < nform.length ; i++) { nstr = nform.elements[i].name + `=' ll = nstr.length jx = 0; while (jx < cl) { k = jx + ll; xstr = astr.substring(jx,k); if (xstr == nstr) { nform.elements[i].value = getCookieAt(k); break ; } jx = document.Cookie.indexOf(" ", jx) + 1; if (jx == 0) break ; } } } function arrayFromCookie() // fills global array from Cookie { astr = document.Cookie cl = astr.length k=0 jx = 0;

for (i = 0 ; i < 6 ; i++) { jx=astr.indexOf(` `,jx) k = astr.indexOf(`=',jx); xstr = astr.substring(jx+1,k); parms[i]=xstr; parms[parms[i]] = getCookieAt(k+1); jx = astr.indexOf(";", jx) + 1; if (jx <= 0 || i > 10) break ; } The function makeYearExpDate() enables you to set the expiration date for several years in the future. It was designed for really persistent Cookies. If you want a shorter time, you can easily modify this routine. Note that this function uses the Date object heavily. The static method, Date. getTime(), returns the date as seconds since The Epoch, while the method, Date.toGMTime(), returns the date converted to Greenwich Mean Time, which is what the Cookie expiration mechanism expects your Cookies to contain. The function fixSep() escapes any semicolons that your variables might have. It is highly undesirable to store semicolons in the Cookie parameters, because the semicolon is the parameter separator. You could, in fact, escape all the nonalphanumeric characters in the entire string. However, this would make it difficult to read, especially if you simply want to look at the Cookie. The function, GetCookieAt(n), retrieves the Cookie value starting at an offset of n characters into the Cookie string. It replaces all escape sequences with their ASCII values. The function, FromCookie(), restores all of the summary form's variables from the Cookie. It is really an undo function. The final function, arrayFromCookie(), is called by the page rebuilding routines to build the global array, parms, from which the page is rewritten. Notice that we can retrieve the value of a single Cookie entry by indexing into the parms array.

Frames and JScript


Frames are one of the most important new features to be added to HTML. Frames allow multiple subwindows--or panes--in a single Web page. This gives you the opportunity to display several URLs at the same time on the same Web page. It also allows you to keep part of the screen constant while other parts are updated. This is ideal for many Web applications that span multiple pages but also have a constant portion (such as a table of contents). Before you learn about the implications of frames on JScript, a very brief tutorial on frames will be presented.

Specifying Frames in HTML


Frames in HTML are organized into sets which are known, appropriately enough, as framesets. In

order to define a set of frames, one must first allocate screen real estate to this frameset, and then place each of the individual frames within it. We will examine the syntax for the HTML FRAMESET and FRAME directives in order to understand how frames and framesets are organized. One of the most important, and most confusing, aspects of frames is the parent/child relationships of frames, framesets, and the windows that contain them. The first frameset placed in a window has that window as its parent. A frameset can also host another frameset, in which case the initial frameset is the parent. Note that a top-level frameset itself is typically not named, but a frameset's child frames can be named. Frames can be referred to by name or as an index of the frames array. You can divide your window real estate with a statement of the form <frameset cols=40%,*>. This frameset statement divides the window horizontally into two frames. It tells the browser to give 40 percent of the window width to the left frame, frames[0], and anything remaining to the right frame, frames[1]. You can explicitly give percentages or pixel widths for all frames, but it is more useful to use an asterisk (*) for at least one parameter. Use this wildcard character (*) for the widest frame, or for the frame that is least likely to be resized. This helps ensure that the entire frameset is displayed on a single screen. You can also divide the window vertically with a statement like <frameset rows=20%,*,10%>. This statement gives 20 percent of the available window height to the top frame, frames[0], 10 percent to the bottom frame, frames[2], and anything left to the middle frame, frames[1].

CAUTION: You cannot divide a window both horizontally and vertically with one frameset. To do that, you must use nested framesets.

The subsequent <FRAME...> statements define the name, source (URL), and attributes of each frame in the frameset. For example, <FRAME SRC='menu.htm' NAME='menuframe' MARGINWIDTH=2 MARGINHEIGHT=2 SCROLLING="YES"> defines a frame into which the MENU.HTM file will be loaded. This frame is named menuframe. Unless you are designing a ledge (a frame that never changes) and you know it will always be displayed in the frame, make the frame scrollable. You can enter an explicit SCROLLING attribute, which should be the value YES or NO, but the frame will default to SCROLLING=YES. Scrolling is much kinder to your users. You might have a very high- resolution display, but a lot of computers, particularly laptops, do not. The MARGINWIDTH= xx and MARGINHEIGHT=xx attributes also allow you some latitude in how you present your document within a frame.

NOTE: Although Internet Explorer and Netscape both understand frames, many other browsers don't yet have that capability. Ideally, you should provide a version of your

document that does not use frames for such browsers. At a minimum, you should warn the users about the presence of frames in your document using a <NOFRAMES>...</ NOFRAMES> clause.

Make sure you have an initial URL to load into the frame, even if that URL is just a stub. Otherwise, you might find that the browser has loaded an index to the current directory. If you want to use a frame in the frameset to load other documents from a link, you must specify the target frame like this: <A HREF='netcom.com/home' TARGET='menuframe'>Microsoft</A> Frames are a sophisticated way to build Web pages; you can keep your menu in one frame and display your content in another. However, it is easy to go overboard and have too many frames. If you present too much information in several different small frames, the user will probably be scrolling quite often. Since the whole purpose of frames is to present information in a pleasing manner, it is important not to try the user's patience. Frames can be a powerful tool, but they should be used judiciously.

Building a Frameset
Framesets are easy to build, although their hierarchy can become complex if they are nested. Listing 17.2 shows a simple frameset document. For it to display correctly, there must be HTML documents with the names given by the SRC attribute in each FRAME definition. When this code is loaded into the browser, the page shown in Figure 17.1 appears. This code appears in the file C17-2.htm on the CD-ROM.

Listing 17.2 c17-2.htm--A Simple Frameset


<HTML> <HEAD> <TITLE><Simple Frame</TITLE> <SCRIPT></SCRIPT> </HEAD> <FRAMESET cols=40%,*> <FRAME SRC="menu_2.htm" NAME="menuFrm" SCROLLING=YES MARGINWIDTH=3 MARGINHEIGHT=3> <FRAME SRC="display.htm" NAME="displayFrm" SCROLLING=YES MARGINWIDTH=3 MARGINHEIGHT=3> <NOFRAMES> You must have a frames-capable browser to <A HREF="noframes.htm">view this document</A> correctly. </NOFRAMES> </FRAMESET> </HTML>

Figure 17.1 Framesets contain multiple frames and reference multiple URLs.

NOTE: When building a frameset, always remember the following rules: The <FRAMESET>...</FRAMESET> block replaces the <BODY></BODY> block. It is incorrect to have both. Always use a <NOFRAMES>...</NOFRAMES> clause for browsers that do not support frames. Make all your frames scrollable except in exceptional circumstances. Make sure the HTML documents referenced by the SRC attributes are "live" before the frameset is displayed.

One of the most difficult concepts about framesets and frames is how they are referenced. For the simple frameset previously shown, you can make a simple roadmap of the object references. When you want to reference the child frames from the frameset, you can use the following references:
q q

MENU_2.HTM = frames[0] or menuFrm DISPLAY.HTM = frames[1] or displayFrm

When one of the frames references its parent frameset, this object reference is used:
q

Either frame = parent

The contents of each frame are referenced as properties of the frame. For example, the frameset can access the document object of MENU_2.HTM as frames[0].document or menuFrm. document. The latter usage is usually preferable, since it is self-documenting.

Frames Within Frames


Frames can be nested in two ways. We will illustrate both types of nesting by putting another frameset inside the displayFrm frame object defined in Listing 17.2. To understand the first method, call the original frameset Frameset A. The frameset declaration shown in Listing 17.3 nests a second frameset, referred to as Frameset B, within Frameset A. It does this by replacing frames[1] (the displayFrm frame) with another frameset. This code can be found in the c17-3.htm file on the CD-ROM. The auxiliary files menu_3.htm, pics.htm, and text.htm are also required.

Listing 17.3 c17-3.htm--Example of Nested Frames in Which a Frame Is Replaced with Another Frameset
<HTML> <HEAD> <SCRIPT> </SCRIPT>

</HEAD> <frameset cols = 30%,*> <frame src = `menu_3.htm' name='menuFrame' marginwidth=3 marginheight=3> <frameset rows=66%,*> <frame src='pics.htm' name='picFrame' scrolling=yes marginwidth=3 marginheight=3> <frame src='text.htm' name= `textFrame' scrolling=yes marginwidth=3 marginheight=3> </frameset> <noframes> You must have a frames-capable browser to <a href=text.htm>view this document</a> correctly. </noframes> </frameset> </HTML> Referencing in this type of nested frameset is no different from the type of object references described for a simple frameset. When a frameset references a child frame, the following object references are used:
q q q

MENU_3.HTM= frames[0] or menuFrame PICS.HTM= frames[1] or picFrame TEXT.HTM = frames[2] or textFrame

When any of the component frames refers to the frameset that contains it, the following reference is used:
q

Any frame = parent

The second method uses URLs to achieve nested framesets. We will set Frameset B's displfrm to an URL that contains a framed document. This URL will come from the file DISPLFRM.HTM and will create the frames picFrame and textFrame. In this case, the object references are somewhat more complex. When the parent refers to its child frames, it uses the following:
q q q q

MENU_4.HTM= frames[0] or menuFrm DISPLFRM.HTM= frames[1] or displayFrm PICS.HTM= frames[1].frames[0] or displayFrm.picFrame TEXT.HTM= frames[1].frames[1] or displayFrm.textFrame

When the child frames refer to their frameset parent, these object references are used:
q q

MENU_4.HTM= parent DISPLFRM.HTM= parent

q q

PICS.HTM= parent.parent TEXT.HTM= parent.parent

CAUTION: Specifying an empty URL in a frame declaration can cause the index file in the server's current directory to be loaded into the frame. Anyone can then open any of the documents listed in that index file. This can be considerably detrimental if you do not want to give users unrestricted read access to that particular directory.

Examples of Interframe Communication


At this point, you know how to refer to parent framesets in frames, and also know the correct object references for child frames of a frameset. The next topic explores interframe communication. This example uses the CD-ROM files C17-2.HTM, MENU_2.HTM (shown in Listing 17.4), and DISPLAY.HTM. Make sure you place all these files in the same directory, and then load C17-2.HTM into your browser. The file MENU_2.HTM that's loaded into the left frame provides a simple and useful example of interframe communication. The MENU_2.HTM file contains some links to well-known sites. A TARGET that points to the displayFrm frame is given for each link. If you click a link, the URL loads into the displayFrm frame instead of into the menuFrm frame. Note that you cannot refer to the "parent" object when you use a TARGET. To experiment with the page, click several links. After you have done this a few times, try to go backwards using IE's Back button. Notice that the whole frameset disappears; it is replaced by the document you were looking at before you loaded the C17-2.HTM frameset.

TIP: Internet Explorer's Forward and Back buttons work on the entire document-not on individual frames.

This limitation can certainly make life difficult, especially if you follow several links in the displayFrm and now want to get back to an intermediate one. Fortunately, there is a way to do this, but you must specifically provide for it. Notice the two small image buttons below the links. If you click the left arrow, the displayFrm frame reverts to the previously visited URL. Similarly, the right arrow takes you forward in the frame.

Listing 17.4 menu_2.htm--Using URLs to Create Nested Framesets


<HTML> <HEAD> <TITLE>MENU.HTM</TITLE>

<SCRIPT> function goback() { awin = self.parent.displayFrm awin.history.back() } function gonext() { awin = self.parent.displayFrm awin.history.forward() } </SCRIPT> </HEAD> <BODY BGCOLOR='darkslateblue' TEXT='linen' LINK='corel' VLINK='darkcorel' ALINK='yellow' > <CENTER><FONT SIZE=7 COLOR="yellow"><B>MENU<B></FONT><CENTER> <H3><HR></H3> <A HREF="http://lycos-tmp1.psc.edu/lycos-form.html" TARGET ="displayFrm">Lycos</A><BR> <A HREF="http://www.yahoo.com/new" TARGET ="displayFrm">Yahoo!</A><BR> <A HREF="http://weber.u.washington.edu/~jgurney/java/" TARGET ="displayFrm">Java Botique</A><BR> <A HREF="http://www.nashville.net/~carl/htmlguide/index.html" TARGET ="displayFrm">How do they do that with HTML?</A><BR> <A HREF="http://www.internet-audit.com/" TARGET ="displayFrm">InternetAudit Bureau</A><BR> <H3><BR></H3> <CENTER> <A HREF=javascript:goback()> <IMG WIDTH=24 HEIGHT= 21 VSPACE=2 HSPACE= 2 BORDER=0 SRC="Images/arw2_l.gif"> </A> <A HREF="javascript:gonext()"> <IMG WIDTH=24 HEIGHT= 21 VSPACE=2 HSPACE= 2 BORDER=0 SRC="Images/arw2_r.gif"> </A> </CENTER> <BR> <H3><BR><HR><BR></H3> <H3><BR><HR SIZE=5 WIDTH=80%><BR></H3> </BODY> </HTML> Another interesting aspect of frames is revealed if you attempt to use the View Source option of Internet Explorer. Only the code for the frameset appears--the code for the frames contained in it does

not. This is one approach to provide some simple protection for your source code. However, it keeps only novice users from seeing your code; experienced users can defeat this by loading the URLs referenced by the individual frames into a single browser window, and then using View Source on that window.

CAUTION: The current release of Internet Explorer does not reliably reload documents containing frames. This means that if you are editing a document and you press the Refresh button, the most recent version of that document might not be reloaded. Images within frames suffer the same problem.

Writing a New Document into a Frame


The examples in the files C17-2.HTM and C17-3.HTM do simple rewrites of documents into adjacent and foreign frames. We will now expand on that by taking the Note Object example from Chapter 8, "Dynamic HTML and IE Objects," and writing it to a frame, rather than to a new window. The file C17-4.HTM on the CD-ROM defines the frameset that loads the subsidiary documents SETNOTE.HTM and NOTE.HTM into its frames. The file SETNOTE.HTM contains a button that calls a writeNote() routine to write the new HTML into the frames[1] frame. The file NOTE. HTM is just a stub so that you don't have to write an empty URL. Listing 17.5 shows the code for the writeNote() function. Figure 17.2 shows what happens when the note is written into the frame. Figure 17.2 Documents can be dynamically written into frames.

Listing 17.5 setnote.htm--The Code for the writeNote() Function


function writenote(topic) { topic = `This is a little note about rewriting adjacent frames." topic += " You do it the same way as you would to rewrite" topic += " or originally write a window." aWin = self.parent.displayFrm ndoc= aWin.document astr ='<HTML><HEAD><BR><TITLE>' + topic + `</TITLE>' astr +='</HEAD>' astr +='<SCRIPT>' astr +='function closeNote(aName){` astr +='self.close()' astr +='}' astr +='function saveNote(aName){` astr +='}' astr +='<\/SCRIPT>'

astr +='<BODY>' astr +='<FORM>' astr +='<TABLE ALIGN=LEFT BORDER><TR ALIGN=CENTER><TD>' astr +='\<INPUT TYPE=button NAME=saveBtn VALUE="Save" ONCLICK="saveNote()" \>' astr +='</TD>' astr +='<TD ROWSPAN=4>' + topic astr +='</TD>' astr +='</TR><TR ALIGN=CENTER><TD>' astr +='\<INPUT TYPE=button NAME=closeBtn VALUE="Close" ONCLICK="closeNote()" \>' astr +='</TD></TR>' astr +='<TR><TD><BR></TD></TR>' astr +='<TR><TD><BR></TD></TR>' astr +='</TABLE>' astr +='</FORM>' astr +='<BR CLEAR=ALL><H3><BR></H3>' astr +='Note: Save button is not active yet' astr +='</BODY></HTML>' ndoc.write(astr) ndoc.close() }

Building a JScript Function Library in a Frameholder


You have already learned that a frameset document cannot contain any HTML other than frame definitions. It can, however, contain a script. In this script, you can keep window global variables and functions. We will define a minimal string manipulator in a frameset. With this tool, you can do the following:
q q q

Change a string to capital letters. Change a string to lowercase. Change all instances of a character.

The first two operations merely require calls to string functions. The latter can be accomplished by a routine that we have already written. You store these functions in the frameset of the file C17-5.HTM on the CD-ROM. This frameset requires the files FUNCS.HTM and EDITOR.HTM to be in the same directory. The frame named menuFrm will contain buttons to call your frameset functions. These functions must be able to refer to objects in their own frame as well as the adjacent frame editFrm. In addition, you must be able to call these functions from the parent frame. The true value of a frameset function library is its reusability. It is easy to copy the HTML file that defines the library and create a new document by changing a small amount of code--the code that builds the frameset itself. In this way, you can reuse your code.

Another way to reuse code is to have all the functions in a small or hidden frame. When you want to use those functions, you simply load that frame. If you take this approach, you don't have to change the frameset code. In both cases, however, it is more difficult to address an adjacent frame than it is to address a parent or child. The menuFrm frame loads the document defined in the CD-ROM file FUNCS.HTM. This file defines the buttons that access the frameset functions. Some of the object references are quite long, so this file makes liberal use of aliasing to shorten them. The file FUNCS.HTM is loaded into the frames[0] object, while a simple editor window is placed in frames[1]. This editor is implemented as a textarea. When this frameset is loaded, the browser will display something like what is shown in Figure 17.3. Figure 17.3 A frameset library can be used to implement a string processor. The file FUNCS.HTM also has a test window and a button, so you can try out the functions it provides. These functions act on objects in its document. The code is such that the button always calls a routine called testit. The testit function has calls to the three routines in the function library. You can easily adapt this code for your own purposes by replacing the testit function. The most complex part of using functions stored in the frameset is determining the appropriate name of the frameset window. This depends on the window from which the function call is made. The example previously shown offers a very simple solution: Just use self.parent.myfunc(). The self portion of this expression can be omitted, but you might want to keep it to discourage ambiguity.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Chapter 9 Creating Your Own JScript Objects


q

Creating Your Own JScript Objects r Global and Local Variables s Parameter Checking r More on JScript Functions s Storing Your Functions s The eval Function r JScripts Associative Arrays s Using Associative Pairs s Arrays of Arrays r Some JScript HTML Objects s Objects Revisited s Images as Objects s The Text Object

Creating Your Own JScript Objects


q q q q

Building a reusable function library Parameter checking and validation Using eval to execute functions written as strings Array initialization and storage

Creating extended and multidimensional arrays In Chapter 4, "JScript Objects," we learned about JScript arrays and their close relationship with JScript objects. That same chapter also taught us how to create functions to do meaningful work. In this chapter, we build upon that foundation and learn how to create complex arrays, functions, and objects. In the process of this exploration, we reveal some of the hidden power of JScript. We begin with a discussion of variable declarations and their relationship to the critical topic of function parameters and their validation. We also build up an extremely valuable function, known as word(), which is used in several subsequent efforts. Associative arrays are one of JScript's most powerful features. They are also one of the most errorprone. The second part of this chapter revisits the topic of associative arrays and examines extensions to them. Since arrays are the only way to store and access information in a database-like manner, we also learn how to fill arrays from lists and use extended arrays.

The final section of this chapter develops two important objects--the Image object and the Text object. The Image object stores a great deal of information about an image, and can also draw that image as a plain image, framed image, or linked image. The Text object stores text and also information about how the text is to be formatted. Both of these objects are developed as arrays of objects, similar to a small database. Both can also be easily extended for your own purposes. Many of the examples in this chapter are too large to be listed in their entirety within the chapter. All the source code can be found on the CD-ROM.

Global and Local Variables


We have already explored the distinction between global variables, which are visible in every function, and local variables, which are visible only in the function in which they are declared. If you want to declare variables global to the whole window, define them outside of any function. Whether you precede the declaration with var or not, it is still global. However, any declarations that you make inside functions should be preceded with var if you want them to remain local. As you know, it is not strictly necessary to declare variables within functions. JScript treats any unknown variable it sees as a new variable, as if you had declared it. If you do not explicitly declare such a variable, or do not precede it with var, it becomes a window global variable. Check your functions very carefully for variable declarations. If you accidentally make a variable a global variable by not using var, it can cause no end to trouble.

TIP: Particular care should be taken with variables having common names, such as i, j, or iter. Always check the declaration of these variables carefully.

It is unfortunate that the rules for the use of var are confusing. Remember that placing var in front of a variable declaration restricts it to the scope in which it is declared. The scope of a variable is the context in which that variable can be used. In the case of a local variable declared in a function, the scope of that variable is the function itself. In the case of a window script, it is the window. If you do not use var in a function or a window script, the variable's scope is global--it can be used anywhere in the window. Although JScript does not force you to declare or initialize variables before you begin function statements, it is often very useful to do so. First, it allows you to document the purpose of each variable. This is not only good programming practice, it is also genuinely useful. When you return to a function six months after you wrote it, you may not remember what the variable countme does, unless you explicitly document it as // array index variable. Second, if you explicitly declare each variable, you have the opportunity to initialize each one to some meaningful default value. The basic rules for JScript functions and their parameters and variables are described in the "Objects,

Properties, and Methods in JScript" section of Chapter 4, "JScript Objects."

CAUTION: If you declare global variables within a function, you must execute the function first for the variables to be defined.

The following code fragment illustrates this idea: function norl() { myFuncVar = 5 } norl() newval = myFuncVar + 3 This code uses the variable myFuncVar inside the function norl. Because there is no var statement preceding the first use of myFuncVar, this variable will become a global variable, but only after the function norl is first executed. As written, the code will operate correctly, and newval will have the value 8. If we modify the third line to read var myFuncVar = 5 and then attempt to execute this code, the alert shown in Figure 9.1 will result. Since the variable was declared with var inside a function, it is local and "out of scope" to anything outside the function. Similarly, if you comment out the call to the function norl() on line 5, this code will also generate the same error. Figure 9.1 JScript alerts you when you have used an undefined variable.

Parameter Checking
Functions, particularly ones that carry out critical tasks like opening windows, should always check to see whether their parameters are valid. This usually involves making sure that they are the correct type or are within some expected range. First and foremost, then, we need routines to determine if the parameters are valid. Strings are relatively safe as parameters, but numbers and Booleans are not. This is because JScript often converts a nonstring, such as 5, to the corresponding string "5," but it converts to numerical or Boolean values only if it can. If a string parameter is specified as the number 5, no error occurs, because the numerical value 5 and the string "5" may be freely converted to each other. If a numerical parameter is specified as the string "five," an error very definitely occurs, because JScript does not know how to convert that string to a number. If you discover a bad parameter, you have two choices. You can simply abandon all processing or you can change the bad parameter to some safe default. It is often preferable to do the latter, and place an error message in a variable that calling routines can check. The library functions which we will develop later in this chapter use two of these; they are aWinErr and aStringErr. Of course,

there is nothing you can do to keep the user from entering something totally unanticipated in a text field. The best you can do is try to limit the destruction that ensues. Now, let's examine a few functions from our repertoire to see how they work. Three checking functions are presented: one for numbers or restricted characters, one for Booleans, and one for character encoding/decoding. Numbers or Restricted Character Sets. The function isIn, shown in Listing 9.1, is multipurpose. It can check to see whether all of the characters in a parameter string are also found within a comparison string. If the comparison string is empty, it uses a string of digits (0--9) as the comparison string. This function returns a Boolean value to indicate if the comparison succeeded or failed. It can also strip unwanted characters from the parameter value and return a string that contains only acceptable characters. The test code is found in the file c9-testr.htm on the CD-ROM.

Listing 9.1 c9-testr.htm--A Multipurpose Parameter-Checking Function


function isIn(astr,nstr,strip) // astr : item in question // nstr : allowable character string; defaults to numbers // strip: determines whether return is true/false // or only allowable characters. Defaults to false. { //declare and initialize variables to make sure they stay local var cc='' var dd='' var bstr = `' var isit var i = 0 // make error string empty aStringErr = `' //force number to a string astr = `' + astr //default to checking for a number if (nstr== null || nstr == `') nstr = `1234567890' //make sure that `strip' is a Boolean strip = (isBoolean(strip)) //force to string; remember, this can return a Boolean strip += `' //NOT a Boolean--complain if (strip == `false') { strip = false aStringErr = `"Value" must be (T/t)rue or (F/f)alse.' aStringErr += `It is neither. Defaulting to false.' alert(aStringErr) return(null)

} //now that everything is set up, let's get down to business isit=false // begin loop which cycles through all of the characters in astr for (i = 0 ; i < astr.length ; i++) { cc=astr.substring(i, i+1) // begin loop which cycles through // all of the characters in nstr for (j =0 ; j< nstr.length ; j++) { dd = nstr.substring(j, j + 1) isit = false if (cc == dd) // so far so good { isit = true // accumulate good characters bstr += cc // no need to go further break } } // end of j loop //you found a mismatch; disqualify the item immediately //unless you are going to strip the string. if (isit == false && strip == `F') break; else continue } // end of i loop if (strip=='T') return bstr // return stripped string else return isit // or return true/false (Boolean) } The isIn() function takes three parameters. The parameter astr is the item to be checked. The parameter nstr contains the set of characters that are permissible in astr. By default, nstr will be "1234567890," which will have the effect of checking to see whether astr is a numerical quantity. The Boolean parameter strip indicates whether unacceptable characters (characters not in nstr) should be stripped out of astr. The first portion of the isIn() function makes sure that astr and nstr are both strings, and initializes nstr to its default value if it was given as the empty string. It also ensures that strip is Boolean (the function isBoolean() is described under "Boolean Validation," as follows). The for loop then examines every character in astr. The substring function extracts each character into the local variable cc and checks to see whether that character may be found in nstr using a second for loop. If any unacceptable characters are found, the isit variable is set to true. This for loop is also responsible for building a new string in the local variable bstr which contains only

acceptable characters. If the strip parameter is true, the function will return the stripped string bstr at the end of its processing. An example of this is shown in Figure 9.2. The characters "l" and "v" are out of range, and are removed. If strip was false, the function returns a Boolean value which indicates whether the astr parameter contained any unacceptable characters. This case is illustrated in Figure 9.3, using the same set of string values. Figure 9.2 JScript functions may convert unacceptable parameters to an acceptable form. Figure 9.3 JScript functions may choose to reject parameters that are out of range. Boolean Validation. When we write code, it is easy to forget exactly how we are supposed to pass a variable. One of the nice things about the JScript language is that it is relatively untyped when compared with strongly typed languages such as Ada or Pascal. In JScript, the same function can return a Boolean, a string, or a number with impunity. The calling routine may have some trouble, though; it complains if you try to hand it a string when it thinks it should get a number. One way out of this dilemma is to forcibly convert the variable to the form you want. You can force an arbitrary value to be a string by concatenating it with an empty string. You can force an arbitrary value to be an integer with parseInt(). The "String Object" section of Chapter 5, "Built-In JScript Objects," discusses string conversion rules and methods. This kind of type confusion occurs frequently with Boolean values. Should a function return true or "true" or "t" or "T" to indicate success? Listing 9.2 shows the isBoolean() routine. It takes the first character of a putative Boolean, changes it to uppercase, and checks to see whether it is "T" or "F". If the resulting value is either "T" or "F", then the function returns true or false, respectively. If the resulting value is neither "T" nor "F", then isBoolean returns false. Note that only the first letter of the astr parameter is ex- amined, so that fear, Fortran, and felicity will all be interpreted as false, while tundra and TECO will be seen as true. Listing 9.2 is also part of the CD-ROM file c9-testr.htm.

Listing 9.2 c9-testr.htm--A Boolean Validation Function


function isBoolean(astr) //astr is the object to check { var isit='' astr +='' if (astr == null || astr == `') isit= false else { astr = astr.substring(0,1) // just first letter astr = astr.toUpperCase() // make it caps

if (astr != "T" && astr != "F") { // unacceptable value entered isit = false } else //returns value which caller can test for true/false //without having to do substrings, etc. isit= astr } //return is mixed: can be either a Boolean or a string. return isit } Character Validation and Conversion. Most languages have a means of defining a character as a numeric code and, conversely, converting the code back to the character. The ASCII standard is often used for this conversion these days, just as EBCDIC was used 20 years ago. All these character encoding systems, such as ASCII, represent each character as a unique numeric value. In ASCII, for example, the space character has the decimal character code 32 (or 0x20 in hexadecimal), the letter "b" has the decimal code 98 (0x62), and the punctuation mark ampersand "&" has the decimal code 38 (0x26). There are many such character encoding systems; some of them also include characters from languages other than English. Chapter 10, "A Java Tutorial," discusses the Unicode international character encoding standard in the section entitled "The Java Language." In fact, if we had functions to convert between the character representation and the numerical representation, many forms of parameter validation would become much easier. For example, an isNumber function, which attempts to determine if a parameter is a number, becomes extremely easy to write. One just examines each variable's numerical ASCII code to see if it is in the range represented by the numerical codes for the characters 0 through 9. These two conversion functions are relatively easy to write. We first need to construct a string that contains all of the printable ASCII characters. We will construct such a string (called the charset string) with a utility function called makeCharsetString(). To convert from the character representation to the numerical representation, we search for the character within the charset string. The numerical representation of that character is its index in the charset string, plus 32. The additional 32 is needed because that is the numerical code of the first printable ASCII character, the space character. To convert from the numerical representation, we reverse the process. We subtract 32 from the numerical value and then extract the character in the charset string at that location. Listing 9.3 shows the asc function, which converts from character to numeric code, while Listing 9.4 shows the chr function, which converts from numeric code to character. The asc() and chr() functions, along with the makeCharsetString() function (which is not listed) will all be found in the c9testr.htm file on the CD-ROM.

NOTE: Case always matters in character encoding. The numerical code for an uppercase letter will always be different from that of the corresponding lowercase letter. For example, b is 98 (0x62) in ASCII, while B is 66 (0x42).

Listing 9.3 c9-testr.htm--A Function to Return the ASCII Code of a Character


function asc(achar) //achar character whose ascii code you want { var n = 0 var csstr = makeCharsetString() //get ascii char string //alert(csstr) for (i = 0 ; i < csstr.length ; i++) { //when you get a match, you have an index into the string if (achar == csstr.substring(i,i+1) )break } //printable characters begin at 32 with [space] return n + 32 }

Listing 9.4 c9-testr.htm--A Function to Return a Character Given an ASCII Code


function chr(x) { var ar = `' var astr = makeCharsetString() //get ascii string //alert(astr) result = `' if (x >= 32 ) // printable { x = x - 32 ar = astr.charAt(x) result = ar } // non printable, return text representation else { if ( x == 9 ) result = `tab' if ( x == 13 ) result = `return'

if ( x == 10 ) result = `linefeed' } return result } Note that there are some strategically placed alert() calls in these functions that are commented out. These alerts are for debugging purposes, to ensure that the functions are actually delivering what you want. Note also that the chr() function does not handle most of the control characters, whose numeric codes are below 32. The only control characters that it tells you about are tab, return, and linefeed. This can be used in an ugly but useful way to insert a carriage return/linefeed combination into a string using the expression + chr(13) + chr(10). There is one additional function we will present. This is the extremely useful word() function, which extracts an indexed phrase from a delimited string. A delimited string is one containing one or more entries separated by a special character referred to as the delimiter or separator. For example, the string "My:name:is:Hanover:Fiste" contains five components--My, name, is, Hanover, and Fiste--separated by the delimiter colon (:).

NOTE: Delimited strings are used frequently in JScript and other loosely typed languages. Delimited strings are convenient because they allow multiple elements to be represented as a single string. Many spreadsheet and database programs, for example, can export their data as delimited strings. The comma (,) and colon (:) characters are frequently used as delimiters.

The word() function is shown in Listing 9.5. It takes three parameters: the delimited string inwhat, the delimiter sep, and the index which of the component required. It returns the component requested. Thus, if you ask word() for the third component of the string in the preceding paragraph, it returns "is." Figure 9.4 shows some sample output from the word() function. In this case, we have used the "@" character as the delimiter and asked for the second item in the string. Note that the word() function uses 1-based indexing.

Listing 9.5 c9-testr.htm--The Delimited String Processing Function word()


function word(sep,which,inwhat) // separator character // which word/pharase // text in which to look { //alert(inwhat) var n = 0 // start of a phrase var wstr = 0 // holds substring

var i = 0 // loop counter var s = 0 // start of winning phrase var f = 0 // end of winning phrase for (i = 1 ; i < which ; i++) { n = inwhat.indexOf(sep,n) // look for separator if (n < 0 ) // if you do not find it { return `' // return empty string } n++ // otherwise, loop again } // now we should be a the right place if ( n >= 0) // ... but do this only if we { // found the separator //alert(n + `==' + wstr) var s = n // phrase starts with n, now s var f = inwhat.indexOf(sep,n) // get next instance of sep if (f < 0 ) f = inwhat.length // but if there is none ... wstr = inwhat.substring(n,f) // must be last phrase in string } //alert(f + `--' + wstr) return wstr // return string; it will be // empty if sep was not found. } Figure 9.4 The word() function extracts an indexed phrase from within a character delimited string. The word() function does its job by using a simple algorithm. The first for loop in this function uses the string method indexOf() to find each occurrence of the delimiter character sep in the input string inwhat. The local variable n is used to hold the current position of the delimiter, while the iteration variable i counts the number of such delimiters found so far. If fewer than the required number which are found, the word() function returns the empty string. If the required number is present, the if test just after the for loop will succeed. At this point, n is positioned at the beginning of the element we want; it is now necessary to locate the end of that element. This will be either the next occurrence of the delimiter or the end of the inwhat string itself. The local variable f is used to hold the location of the end of the element. Once n and f have been computed, the word() function uses the substring() method to store the desired element in the local variable wstr, which is then returned as the value of the word() function.

More on JScript Functions

You may recall from Chapter 4, "JScript Objects," that functions are developed by declaring them within a script. This section briefly reviews some of things to remember when writing functions, and then delves a little deeper into some of the fine points of functions in JScript. This material is developed further in the next section on associative arrays. Make sure that you declare your most elementary functions earliest in the header script. This ensures that later functions are able to use them. The same rule applies to objects. Make sure that you do not reference any objects that have not yet been created in any of your functions. Functions in a header script cannot see objects created by the HTML on your page, nor can they see objects created by code executing later in the script. If there is something that must be done with an HTML-generated object, place it in a footer script. Proper error-checking is also very important. If a function fails, provide a mechanism for the calling routine to detect the failure. If you can, try to keep the damage to a minimum. It is a sign of very poor design when an Internet Explorer Error dialog box comes up immediately after your page is loaded. One major problem with using functions has to do with passing the parameters in incorrect order. If some function expects three parameters that represent two numerical values and a string, but you give it a numerical value, a string, and then the second numerical value, an error very likely will occur. A similar problem arises when a calling function misinterprets what should be passed in a parameter. If a function relies on unchecked input from a user, check that the parameter is at least of the right type. If you detect that it is incorrect, flag it and, if you can, fix it.

CAUTION: Make sure that all local variables within a function are preceded by var. If a function inadvertently declares a global variable that has the same name as a local variable in another function, inexplicable behavior will often result. In particular, function parameters may become garbled. This type of error is particularly difficult to diagnose, so special care should always be taken with variable declarations.

Storing Your Functions


JScript cannot read (or write) local data files, but it can load and use HTML files. Therefore, even though you cannot create a JScript function library in an ordinary file, you can write a function library in an HTML header and load that library inconspicuously when you want to use it. Function libraries can also be used with frames by designating one particular frame as the "owner" of the library. All of the other frame documents have a global variable called funcs, which refers to that special frame from the perspective of the calling frame. Consequently, you can call a function named myfunction in the function library by using the reference funcs.myfunction from anywhere in any of the nested frames. You can also make a function library in a frameset itself. The "Bug Database" section of Chapter 17, "Using Frames and Cookies," provides a comprehensive example of using a function library with frames. Note that the functions given here are meant to be introductory only. Because JScript at present lacks

many of the functions that have become standard in most programming languages, we have provided you with a library of some commonly used functions. They can be found in the file C9-TESTR.HTM. This HTML file not only contains the functions in the previous listings, it also creates a little test page that allows you to enter parameters and call a given function with them. It is also useful if you want quickly to look up an ASCII code or convert some HTML text to a form in which it can be displayed by the browser without being interpreted as HTML by the browser.

The eval Function


In HyperCard, one can write Hypertalk in a text field and then "do" the field, which executes the contents of that field. Because of this, your HyperCard scripts can write and execute code on-the-fly. You can do something similar in JScript using eval(). Although eval() sounds as if it should be used only to evaluate mathematical equations, this function can actually do much more. It can evaluate any string that is a JScript statement. Try this experiment. Create an HTML button and attach the following statement as its onClick event handler: eval(`alert("I did it!")') When you click the button, the Alert box pops up. In the same way, you can pass the contents of an HTML text field or textarea to a JScript event handler. This is illustrated by the function evaluate (), which is found in the file JS-EVAL.HTM on the CD-ROM. This function consists of a single line of code, eval(what). A single HTML button arranges to pass the contents of a textarea to this function, which promptly tries to execute the contents of that textarea as JScript code. The eval statement can be placed directly in the button handler, of course. By placing it in the separate (but trivial) evaluate function, we make it easier to extend in the future.

JScripts Associative Arrays


Associative arrays were introduced in Chapter 4, "JScript Objects," and have been used in several previous chapters in this book. You are already aware that an associative array is a one-dimensional array of pairs. You access the left member of the pair with a numeric index. You access the right member of the pair with a string index equal to the value of the left member of the pair. For example, (left) myArray[1] = "red" but (right) myArray["red"]= "FF0000". Arrays can be created in two ways: by using the new operator on the built-in Array object, or by writing a special-purpose function that takes a generic this object and gives it a size. If you use the former approach, you must specify the number of elements; you may also optionally specify a list of initializers. If you use the latter method, you can also create other properties for the array in the special-purpose function. To actually create the array, you use the new operator together with your special array creation function. For example, if we use the createArray function shown as follows, the statement: myNewArray = new createArray(6,'') creates an array called myNewArray with six elements and initializes all of the left members to `'.

Note that this is not being done for you by JScript in some magical way. You have to write the creation function and then invoke it with the appropriate parameters. An array is a primordial JScript object. Its properties, which represent the array members, can be anything. You must set the special property known as length, however, in your creation function. This property gives the length of the array (and is occasionally referred to as the size property). The length property is usually put in the zeroth element of the array during initialization. This means that your arrays will actually have n+1 elements in total: n elements for data, and one extra element at index zero to hold the array size. You need to be sure that your array access functions do not overwrite the zero element. Listing 9.6 shows a general purpose createArray() function.

Listing 9.6 A General-Purpose createArray Function


function createArray(n, init) { this.size = n //This initialization is absolutely necessary for (i = 1 ; i <= n ; i++) { this[i] = init //Initialize all of the left hand elements } return this //Return the array object to the caller } Notice that there is no initialization of the right members of the array. You can arrange also to do this in the createArray function, but only with some effort. This is because the left element must be unique, and we have initialized all the array elements to the same value, namely the value init. If you have two array members containing the same value, you are able to get only to the first one. In addition to creating arrays, it is often desirable to be able to reset or clear an array so that it may be reused. A special procedure known as a double replacement scheme must be used to clear or reset an existing array. (You can always create a completely new array, of course.) This special approach is needed because you have no way of knowing what values are already stored in the array. In particular, you have no way of knowing that they are unique. The double replacement method uses the following loop to safely reset the array myArray: myArray[i] = `@@@@@' myArray[`@@@@@'] = `' myArray[i] = `' This method uses a special dummy replacement value to manipulate both the left and right sides of the pair. In the preceding example, the string `@@@@@' is used. To avoid the problem of nonunique indices, this dummy value must be highly unusual so that it is extremely unlikely actually to appear in the array. CAUTION: Do not try to initialize the right side of an array in the same loop in which

you initialize the left side. JScript mixes left and right values for you. If you need to initialize the right side, do it in a separate loop.

Using Associative Pairs


Associative arrays occur far more often than you might think. They occur even in everyday life, although most people do not think of them that way. The picture on the top of a TV dinner box is related to what is in the box. You choose your dinner by looking at the picture because the picture conjures up thoughts of what is in the box. You would not open every box in the freezer and examine its actual contents in order to decide which one to put in the microwave. Programmers tend to think of an association in somewhat less colorful terms such as a = b, x = 3y2, and so on. A Windows .INI file is an excellent example of the use of associative pairs. Every entry has a left element, such as *. DOC, and a right element, such as C:\WINWORD\WINWORD.EXE. In this case, the association is a relationship between a file suffix and the application that created it. Hypertext links are also associations; they are just ordered backward. The following HTML: <A HREF='http://www.myfavoritelink.com'>My favorite link</A> is actually an associative pair. If we were to place this into an array, most of us would place My favorite link on the left side, and `http://www.myfavoritelink.com' on the right. We often reference complicated, large, and sometimes obtuse objects with less complicated words or nicknames. An Enhanced Array Object. A simple associative pair array may not be sufficient for your needs. Because an array is just an unstructured object, we can conveniently make it into a more complex object. For example, we can add a description property to an array. This is useful because the array may have a short name that is easy to use elsewhere in our code, but that name may not be very illustrative of the array's purpose. Another property we might want to add is a property that reflects the "element of interest right this minute" or the "current" element. An example of this might be the strings in a list box. The current property could refer to the currently selected item. This might be called the currentIndex property, or, more tersely, the nDx property. (Remember that JScript is case-sensitive.) Finally, if we are using the list as some kind of a stack, or if we are keeping track of items that are constantly being added or deleted from the list, we might need to know where the next open slot is located. We will call this property the nextIndex property. But where do we put these properties? Well, properties are just array elements, so the question is where in the element list they should be placed. If we put them at the beginning, the array elements proper do not start at index=1. If we put them at the end, the array elements are in the right place, but it is now more difficult to increase the size of the array. This is because there are referencing problems if you access the properties by their array index rather than by their names. We will examine the advantages and drawbacks of both approaches. Array Initialization and Storage. While associative arrays are an extremely powerful programmer tool, there are some pitfalls in using arrays. Most of them stem from a lack of initialization or from incorrect initialization. The file c9-array.htm on the CD-ROM contains several array initialization and array manipulation functions. Various array functions are given that present different approaches

to the location of the enhanced array object properties, such as currentIndex and nextIndex, and how (or whether), the array is initialized. The page generated by this file has buttons to allow you to initialize various arrays, reset them, clear them to null, enter a single value, and fill the arrays. Each array is treated in the same fashion. After you have exercised one or more of these functions, you can then look at the contents of each array to see the effect. The array creation functions are organized into two categories: those that place the enhanced properties at the end, and those that place the enhanced properties at the beginning. The first four array creation methods place the enhanced properties at the end of the array and initialize all empty slots to @. They differ in how they handle the enhanced properties. The final three creation methods place the enhanced properties at the beginning of the array. This set of methods can be used to examine the consequences of not initializing the array or initializing all of the elements (including those of the special properties) to the same thing, and of initializing only the empty elements. These functions are obviously not the only possible ways in which such array functions can be written. Listings 9.7 and 9.8 show two of these functions. Notice that it is not possible to create an uninitialized array and still place the extended properties at the bottom.

Listing 9.7 c9-array.htm--A Function to Create an Array with Special Properties Added at the End
function createArray1_d(n,init) { var i = 0 this.length = n + 3 for (i = 1 ; i <= n ; i++) { this[i] = init } this.description = `desc' this.nDx = `nx' this.nextIndex = `ni' return this }

Listing 9.8 c9-array.htm--An Array Creation Routine with Extended Properties at the Beginning
function createArray3(n,init) { var i = 0 this.length = n + 3 this.description = `dc' this.nDx = `nx' this.nextIndex = `ni' for (i = 4 ; i <= n + 3 ; i++)

{ this[i] = init } return this } When you first load the c9-array.htm page, as shown in Figure 9.5, all of its arrays have been created; those arrays which initialize themselves have done so. Initialization has been done only for the left elements. No initialization has been done for the right elements. The viewing routine has been set to look at the first unused element. This will be the element at index n + 1, which is not yet processed or initialized in any way. For purposes of this discussion, we call those array elements that are not directly related to a property the empty elements. Those that are associated with properties are called the special elements. Each element consists of a left and right element. The left element of the zeroth element of the array has the array size in it.

CAUTION: Platform dependencies have been reported in the current release of Internet Explorer. You may find array functionality to be different depending on the platform on which you are running the browser. Try the code in c9-array.htm and c9arrx.htm as test cases.

Figure 9.5 JScript's associative arrays can be accessed using numerical or named indices. First, let's look at the those arrays that have the special elements at the end of the array. Click the 1a button. This creation routine initializes all of the empty elements to "@" and the special elements to "". Did you expect to see the property names in the special elements? They do not appear here. They are properties associated with the array object, not values within the array object. This creation scheme works as you would expect. Before you breathe a sigh of relief, let's look at the next array creation method (associated with button 1b). Because we could not tell which element was which, we decided to initialize the left side of each special element with the name of the property associated with it. All the empty elements have the initial value @ and all the special elements are dutifully null, as shown in Figure 9.6. Figure 9.6 JScript fills uninitialized associative array values with null. Button 1c manipulates an array in which all of the special elements have been initialized to the same value as the empty elements. There are no surprises here. The final creation method of the first series, method 1d, initializes the special elements to two unique characters for each related property. Once

again, the behavior is quite uniform. The three creation methods in the second series put the special elements at the beginning of the array. Using the first of these three methods, it is possible to produce a completely uninitialized array. Still, nothing unusual happens; the empty elements are just null. The second of these creation methods initializes both the special elements and the empty elements. The very last creation method initializes only the empty elements; it also behaves properly. Instead of clearing or reinitializing the arrays at this point, click the rightmost button named Enter One Value/Array. This button does exactly that. It enters a "red","FF0000" pair into anArray [2] for those arrays with special properties at the end and into anArray[6] for those arrays with special properties at the beginning. The array created by method 1a offers up no more surprises in this case. The value pair has been entered in the correct place. Notice that the array uses one-based indexing in terms of reference as well. The arrays created by the other methods with the special elements at the end (methods 1b2 through 1c) are also well-behaved, as are the three methods with the special elements at the beginning To continue our array experimentation, let's reinitialize the arrays, preferably by reloading the file. Then click the Fill Arrays button. This fills the empty elements of the array with pairs in the form of name=month. Repeat your inspection process, and you should uniformly see something like Figure 9.7. Figure 9.7 Entering data into an uninitialized array fills in the values. You can perform a variation on this experiment by reinitializing the arrays and then clearing them using either method. Use the Initialize and Clear (or Clear to Null) buttons, and then add a single value to all of the arrays or simply fill the arrays. The unused elements may be quirky, but the array elements themselves behave properly. The companion page in the file C9-ARRX.HTM provides a variation on the same theme. It is the same as the code in C9-ARRAY.HTM, except that all its arrays have an extra uninitialized element just after the original eight array elements. As before, a first unused element is displayed. It is worthwhile to go through the same procedures and see how the various arrays behave.

CAUTION: Initialize your arrays before you use them! Uninitialized arrays cannot be trusted to provide correct results when referenced. They cannot even be trusted to provide consistently incorrect results, and can be a nightmare to debug.

Filling Arrays from Paired Lists. Listing 9.9 is worth special attention. It provides a function named fillArrayFromLists() which will fill the associative pairs of an array from two

parallel lists of delimited elements. It is a lot faster to write such lists than it is to specifically set each right and left element in an array. This function uses the library function word(), which was described earlier in this chapter. You may recall that this function uses a character delimiter to separate the elements in the list. The separator can be any character; the most common one is a comma (,). HyperCard enthusiasts will recognize this as an item list. The fillArrayFromLists function will be found in the file c9-array.htm on the CD-ROM.

Listing 9.9 c9-array.htm--A Function to Load an Associative Array from Two Delimited Lists
function fillArrayFromLists(anArray,aaList,bbList,sep,s,f) { var lstr = `' // left hand array element var rstr = `' // right hand array element var i = 0 // iteration variable var counter = 1 for (i = s ; i <=f ; i++) { anArray[i] = word(sep,counter,aaList) anArray[anArray[i]] = word(sep,counter,bbList) counter++ } } This function takes six parameters: the array anArray, whose values are to be set; two delimited strings, aaList and bbList, which hold the right and left elements; the string delimiter sep; and the first s and last f indices in anArray, which are to be set. The function executes a simple for loop over all the array indices from s to f, inclusive. In each iteration, it calls the word() function twice to extract the right and left elements from aaList and bbList. As a demonstration of the power of this function, let us invoke it using two short lists. In our case, we use the asterisk character (*) as the delimiter. The following code shows each person on the list aList being associated with a particular month, as given in the list bList: var aList = `Mona*Jane*Barbara*Sandra*Maxine' var bList = `January*March*September*February*December' fillArrayFromLists(array1,aList,bList,'*',1,5) Using the Enhanced Array Object. Now that we have created our enhanced array object and dissected it at great length, how can we use it and which version should we adopt? Although all of the creation methods we have tested work if the array is properly initialized, we will use the final version of the methods that place their special properties first in our subsequent code. This is the one that did not overwrite our special properties. Most of the time, only the left elements of the associative pair are used, but these lists can also hold an associated object (right element).

TIP: The enhanced array object can be used to implement a string list, object list, or a stack.

One array that arises frequently in JScript applications is an array of newly created child windows, because JScript does not provide such an array by default. Listing 9.10 shows the function winArrayAdd(), which can be used to add a window to such a window array. Note that this function uses global variables to keep track of the next available array slot (in nextWin) as well as the current window (in curWin).

Listing 9.10 A Function to Add a Window to a Window-Tracking Array


function winArrayAdd(aWinHdl) { // set next open slot in winArray to hold this window handle // and that window's creator aWinArray[nextWin] = aNewWin aWinArray[aWinArray[nextWin]] = aNewWin.opener curWin = nextWin // make this the current window nextWin++ // increment next available slot pointer } Instead of using global variables, we can, of course, use an array with special properties as well. The code in Listing 9.11 illustrates this form of the window addition function. While Listing 9.11 does not look much different from Listing 9.10, the latter version is the preferred one. This is because it keeps essential window-tracking information together. Other functions may therefore access all the relevant data by simply examining appropriate elements of the array, rather than having to look at the array and also consult some global variables.

Listing 9.11 A Better Version of the Window Add Function Using Special Properties
function winArrayAdd(aWinHdl) { // set next open slot in winArray to hold this window handle // and that window's creator aWinArray[aWinArray.nextIndex] = aNewWin aWinArray[aWinArray[nextWin]] = aNewWin.openerr // make this the current window aWinArray.ndx = aWinArray.nextIndex nextWin++ // increment next available slot pointer }

Arrays of Arrays
One of the biggest criticisms of associative arrays is that they are one-dimensional. The argument can be made that the left and right sides constitute a second dimension, of size two, but this is not really a true multidimensional array. In fact, two-dimensional arrays are really just arrays of arrays. Because of the nature of associative arrays, one can develop such complex structures with relative ease. Simulating Multidimensional Arrays. Imagine, if you will, an array of colors. In a simple implementation of such an array, the left element contains the name of the color, such as "red," and the right member contains the hexadecimal value for the color. For red, this value is 0xFF0000. There are many shades of red, however. Of course, we could add all of these variant names to the array. It would be much nicer to be able to go to an array, find "red," and then access into a list of colors which were various shades of red. Let's now construct an example in which we can do that. As usual, the left element is initialized to "red." The right element, however, holds a handle to another array called moreReds. The array moreReds contains the typical colorname=hexvalue pair. Listing 9.12 shows a very simple way of creating such a multidimensional array.

Listing 9.12 A First Approach to Creating a Multidimensional Array


colors = new createArray(9,'') moreRed = new createArray(20,'') moreYellow = new createArray(20,'') moreOrange = new createArray(20,'') moreBrown = new createArray(20,'') moreGreen = new createArray(20,'') moreBlue = new createArray(20,'') morePurple = new createArray(20,'') moreGray = new createArray(20,'') moreWhite = new createArray(20,'') ... Not only is this tedious, but it's not even a complete solution. We have to put each of these secondary arrays into the right elements of the first array. There must be an easier way to do this. We need to develop an approach to getting the various values into the multidimensional array and getting them out again. Listing 9.13 contains three functions. The createArray() function is very similar to the array constructor we have already seen. The fillcolorArray() function fills both the left and right elements of an associative array, which is passed in as a parameter. This means that if you execute the statement: anArray = fillColorArray(anArray,'green','gr') the left elements are filled with green1, green2,..., and the right elements are filled with gr1, gr2,.... The third function, lotsOfColors(), is used to orchestrate the creation and

initialization of this array. This function also uses our old friend the word() function. One might think of using eval() to metamorphose a constructed string into an array handle, as in the following statement: dstr = eval(dstr = new createArray(20,'')) In fact, this is not necessary. Here, we see another tribute to the flexibility of JScript variables, because the following statement works just fine: dstr = new createArray(20,'') Try this in C or Pascal! The resulting value of dstr is then passed to fillColorArray() to be stuffed with values. When this function returns, dstr is plugged into the right value of the current array pair.

Listing 9.13 Three Functions Used to Create an Associative Array of Associative Arrays
function createArray(n,init) //n size of array //init what you want all values initialized to { var i = 0 this.length = n // set the size of the array for (i = 1 ; i < n ; i++) { this[i] = init // fill the array with "init" } return this // return the newly created array } function fillColorArray(anArray,init,init2) // anArray is the array to be filled // init holds the values for the left side // init2 holds the values for the right side { var i = 0 var astr = `' var bstr = `' var n = anArray.length // get array length for (i = 1 ; i <= n ; i++) // iterate over each element { astr = init + i // get left value bstr = init2 + i // get right value anArray[i] = astr // set left

anArray[astr] = bstr // set right } return anArray // return modified array } function lotsOfColors() { var cstr // colors will be an array of 9 colors // colorstring will be the names of those colors, delimited by commas var colors = new createArray(9,'') var colorstring = `red,yellow,orange,brown,green,blue,purple,gray, white' for (i = 1 ; i <= 9 ; i++ ) // iterate over array { // extract the i-th element cstr = word(`,', i , colorstring) colors[i] = cstr // set left value dstr = `more' + cstr // create and initialize right value in next two statements dstr = eval(dstr = new createArray(20,'')) dstr = fillColorArray(dstr,cstr,cstr.substring(0,2)) colors[colors[i]] = dstr // set right value // next three statements are for debugging // they display the values set in an alert astr = colors[cstr][3] bstr = colors[cstr][astr] alert( astr + `\n' + bstr) } } The function lotsOfColors() warrants close attention. It starts off by creating the associative array, colors, as well as a comma-delimited string that lists the colors it uses. It then cycles through a loop for each color to be processed. It first extracts the color we want from colorstring (as a string) and then sets the left element of the current associative pair to that string. Thus, colors[1] yields "red." That's the easy part. How do we name the array handles that we place into the right member? We can construct an element named "moreRed," but the "moreRed" is a string. Fortunately, JScript permits a string to be enough of a chameleon that it can be turned into an array handle.

CAUTION: Arrays should be initialized and filled in different routines. If you attempt to perform these operations in the same routine, strange substitutions, which are symptomatic of an uninitialized array, will result.

Using a Multidimensional Array. So far, we have not tried to access the secondary members of this construction. Surprisingly enough, that is not much harder than accessing the usual one-dimensional associative array. In fact, the debugging code at the end of lotsOfColors() already shows how this is done: astr = colors[cstr][3] bstr = colors[cstr][astr] alert( astr + `\n' + bstr) The variable astr holds the left element, and bstr the right element. If you attempt to do this in one step, it appears confusing. If you substitute the value of astr in the second expression, you get the following massive expression: bstr = colors[cstr][colors[cstr][3]] Note that we placed some convenient but arbitrary values into our subsidiary arrays. We could have had the fillColorArray() function generate successive, properly spaced hex values that were within the appropriate color range. In general, it is more likely that you will want to use these kinds of arrays to keep arbitrary data.

Some JScript HTML Objects


This section reviews some of the fundamental concepts of HTML objects in JScript, and then proceeds to the more complex Image and Text objects described at the beginning of this chapter. By this point, you are well acquainted with the various HTML objects in JScript. The focus of this section is to explore some of their innovative uses. Many of the "tricks" of JScript revolve around its polymorphism, namely its capability to view a single thing in different ways. JScript strings provide an excellent example of this polymorphism. Strings in JScript can be thought of as HTML objects, in addition to their usual meaning. This is because JScript provides methods for giving strings many of the formatted characteristics of HTML text, such as bold (<B>), italics (<I>), big (<BIG>), link (<A>), and so on. When you use a construction such as: mystring = `This is some text.' mystring = mystring.bold, mystring becomes <B>This is some text.</B>. We will use methods such as these in the Text object we create. HTML string methods are discussed in great detail in the "String Object" section of Chapter 5, "BuiltIn JScript Objects."

Objects Revisited

By now, you are intimately aware that objects are just arrays of properties. However, properties are accessed somewhat differently from array elements, and they usually only use the left side of the array. New properties can be added to an object at any time. This is possible because only the left element of the array is used. Trying to add new array elements on-the-fly when you are using both sides of the array element is fraught with peril, as we have seen previously. Objects can have properties or methods. Methods are simply functions that have been declared as properties. For example, you might have a color object. Colors are cited in terms of their red, green, and blue components (at least in Web browsers; there are other color-mixing schemes). Many of the common colors also have common names. To declare a color object, we must make a constructor/creator, as shown in Listing 9.14. This is no different from the type of construction methods we have seen for arrays.

Listing 9.14 Creating a Simple Color Object


function createColor(name,red,green,blue) { this.name = name this.red = red this.green = green this.blue = blue this.length = 4 return this } myGreenColorObject = new createColor(`green','22','DD','22') Property Taxes. Object constructors really just reserve space for the property array elements. We can access the property values by their array indices, as well as by using the dot operator (.). This is sometimes extremely useful for storing objects. To convert the color object into a string delimiter with the @ character, the code in Listing 9.15 might be used. This type of string is often useful for storing objects persistently, as we shall see in Chapter 17, "Using Frames and Cookies." Cookies may be used to store objects represented as delimited strings. The "Cookies" section of Chapter 17, "Using Frames and Cookies," describes this approach in great detail.

Listing 9.15 Storing an Objects Properties as a Delimited String


function storeColor(aColorObject) { var k = aColorObject.length // number of elements in object var astr = `' // initialize to empty string var i = 0 for(i = 1 ; i <= k ; i++) // iterate over elements { astr += aColorObject [i] + `@' // append to astr. }

return astr // return delimited string } You can easily reverse this process, as Listing 9.16 shows. The function getColor() undoes the work done by the function storeColor of Listing 9.15. It tears apart the delimited string passed as its second argument astr, and sets the properties of aColorObject accordingly.

Listing 9.16 Retrieving an Objects Properties from a Delimited String


function getColor(aColorObject,astr) { var lastloc = astr.lastIndexOf(`@') // final delimiter var n =0 // number of delimiters found var f = 0 // location of current delimited var i = 1 // current array index while ( n >= 0 ) { // find next delimiter, store in local variable f f = astr.indexOf(astr,n) // set the i-th array element to the string between the last delimiter // ( at location n ) and the current delimiter ( at location f ) aColorObject[i] = astr.substring(n,f) // if we are at the very last delimiter ( at location lastloc ) if (f == lastloc) { // then take the substring from the current position up to the end // of the string and break out of the while loop aColorObject[i+1] = astr.substring(f+1,astr.length) break } // if we are not at the very last delimiter then repeat the process else n = f + 1 // update array index i++ } } These examples are not the only ways to perform either of these operations. The storage function storeColor() of Listing 9.15 could also have been implemented as shown in Listing 9.17, for example. We could also use the word() function to retrieve the properties of an object from a string in the getColor() function. This would be slower than the approach shown in Listing 9.16, however.

Listing 9.17 An Alternative Color Storage Function Using the for..in

Statement
function storeColor(aColorObject) { var astr = "" for (var i in aColorObject) astr += aColorObject[i] + `@' return astr } Creating Your Own Methods. It would be nice if the color object knew how to do its own conversion to and from the delimited string representation. Because we have already written the essential conversion functions, it's easy to make them methods of the color object: We just assign them as properties of the object itself. If we use this approach, our color object constructor is as shown in Listing 9.18.

Listing 9.18 Creating a color Object with Methods and Properties


function createBetterColor(name,red,green,blue) { this.name = name this.red = red this.green = green this.blue = blue this.toString = storeColor this.fromString = getColor this.length = 6 return this } myGreenColorObject = new createBetterColor(`green','22','DD','22')

NOTE: Always set the length property of an object in your constructor. Although the current implementation of JScript will automatically create a length property in the element at index=0, and keep that length property updated as new elements are added, this behavior is not guaranteed.

If you are going to convert a function into a method, you can (and should) alter it somewhat to exploit the fact that it is now a method function. If a function is not a method function of an object, then it may access that object only if the object is passed as a parameter to the function, or if the object has been declared globally. Once you make the function a method of the object, the function can reference the object that contains it via the keyword this. Consequently, we can rewrite the

storeColor method to look like Listing 9.19.

Listing 9.19 Storing an Objects Properties Using a Method Function


function storeColor() { var k = this.length var astr = `' var i = 0 for(i = 1 ; i <= k ; i++) { astr += this[i] + `@' } return astr }

NOTE: In order to change a function into a method function of an object, follow these three steps: 1. Make the method a property of the object, as in aColor.toString = storeColor. 2. Do not pass the object as a parameter to the function. 3. Change all explicit references to the object to the keyword this; for example, 1 = aColorObject.length becomes 1 = this.length.

Images as Objects
Drawing images is a complex affair. One of the most important things to remember about image manipulation in terms of JScript is that all images must be characterized by HEIGHT and WIDTH modifiers in their HTML tags. If you leave these modifiers out, JScript will misbehave or won't function at all. We will create an Image object that encapsulates all the important Image properties, including the height and width. The Image object will also know how to display itself in several contexts. The constructor for the Image object is shown in Listing 9.20. All of the code for the Image object will be found in the file c9-image.htm on the CD-ROM.

Listing 9.20 c9-image.htm--A Comprehensive Constructor for an Image Object


? function createImage(title, filename, height, width, vspace, hspace,

border, bordercolor, frame, framecolor, href, notes) { this.title = title this.filename = filename this.height = height this.width = width this.vspace = vspace this.hspace = hspace this.border = border this.bordercolor = bordercolor this.frame = frame this.framecolor = framecolor this.href = href this.notes = notes this.draw = drawImage this.frame = frameImage this.reference = referenceImage this.popup = popImage return this } Properties and Methods of the Image Object. If you examine the constructor for the Image object shown in Listing 9.20, you see that it not only encapsulates the normal HTML qualifiers for an image, but also has properties for a file spec, a title, an associated URL, and notes. It can present itself as a plain image, a framed image, or a linked image. It can also pop itself up in a window of its own. The image "draws" itself by presenting you with a string that you can send to a nascent document using document.write(). The code in Listings 9.21, 9.22, and 9.23 shows the methods used to draw a plain image, a linked image, and a framed image. Documents created on-thefly, also known as nascent documents, are discussed thoroughly in the "Nascent Document" section of Chapter 8, "Dynamic HTML and IE Objects," p. 229.

Listing 9.21 c9-image.htm--The Image Objects Plain draw Method


function drawImage(how,border) { var astr = `' // if the image does not use this modifier // the parameter can be empty or `^' astr = `<IMG SRC="' + this.filename + `"` if (how != `') astr += ` ALIGN=' + how if (this.height != `') astr += ` HEIGHT=' + this.height if (this.width != `' && this.width != `^') astr += ` WIDTH=' + this.width if (this.vspace != `' && this.vspace != `^') astr += ` VSPACE=' + this.vspace if (this.hspace != `' && this.hspace != `^')

astr += ` HSPACE=' + this.hspace if (this.border != `' && this.border != `^') astr += ` BORDER=' + this.border astr +='>' if (this.border != `' && this.border != `^') astr = `<FONT COLOR=' + this.bordercolor + `>' + astr + `</FONT>' return astr }

Listing 9.22 c9-image.htm--The Image Objects Linked draw (Reference) Method


function referenceImage(how,border,ref,atext) { if (ref == `') ref=this.href if (ref == `') ref = location.href if (atext == `') atext = `Your text here!' var astr = `<A HREF=' + ref + `>' astr += `<IMG SRC="' + this.filename + `"` if (how != `') astr += ` ALIGN=' + how if (this.height != `') astr += ` HEIGHT=' + this.height if (this.width != `' && this.width != `^') astr += ` WIDTH=' + this.width if (this.vspace != `' && this.width != `^') astr += ` VSPACE=' + this.vspace if (this.hspace != `' && this.width != `^') astr += ` WIDTH=' + this.hspace if (`' + border != `') astr += ` BORDER=' + this.border astr +='>' astr += atext astr += `</A>' return astr }

Listing 9.23 c9-image.htm--The Image Objects Framed draw Method


function frameImage(how,border,leading) { var astr = `<TABLE ` if (how != `') astr += ` ALIGN=' + how if (`' + border != `') astr += ` BORDER=' + border if (`' + leading != `') astr += ` CELLSPACING=' + leading astr += `><TR><TD ALIGN=CENTER>' var bstr = `</TD></TR></TABLE>'

astr += this.draw(`',2) astr += bstr return astr } Notice that the frameImage method essentially draws the table structure, which is the "frame," and then calls the drawImage method to draw the image. In all cases, the image can have a border. In both the drawImage and frameImage methods, the border color is determined by the current font color. Because the Image object encapsulates the border color, it is as easy to include it as it is to include any other modifier. Referenced image borders, though, do not have such a choice; they will be the link color or vlink color specified for the page. Using the Image Object. You can use the Image object to make a database of your images. A file name, notes (which can include a caption for the image), and an URL are included as part of the object, as we have seen. The example program on the CD-ROM (file C9-IMAGE.HTM) arbitrarily sets up a trivial database of six Image objects held in an array. It can present these images as plain, framed, or referenced. It can also pop up any image in its own window. Listing 9.24 shows the method function that creates the pop-up.

Listing 9.24 c9-image.htm--The Pop-Up Method of the Image Object


function popImage(title) { var w = 50 + parseInt(this.width) // image width as displayed var h = parseInt(this.height) + 50 // image height as displayed scrl = `no' // do scrolling? if (w>640){w=640;scrl='yes'} // if width too big them scroll if (h>480){h=480;scrl='yes'} // if height too big then scroll // create HTML attributes for the image var whstr ='WIDTH=' + w + `,HEIGHT=' + h + `RESIZABLE=yes,SCROLLBARS=' + scrl // open a new window aNewWin = self.open(`',title,whstr) // if the new window could not be created... if (!aNewWin) { // notify the user that it failed, and try to indicate // possible causes var alertstr = "Could not open a new window." alertstr += " A window of named " + title alertstr += " may already be open." alertstr += " You may also be out of memory" alert(alertstr) return; } // if new window was created successfully...

// create the HTML to display the image var astr = `<HTML><HEAD>' astr += `<BASE HREF="' + location.href + `">' astr += `<TITLE>' + this.title + `</TITLE>' astr += `</HEAD><BODY>' // write out that HTML aNewWin.document.write(astr) var bstr = `<CENTER>' + this.draw(`CENTER') + `</CENTER>' aNewWin.document.write(bstr) aNewWin.document.write(`</BODY></HTML>') // close the document aNewWin.document.close() } The resulting image display is shown in Figure 9.8. The page generated by the CD-ROM file c9image.htm is covered with pop-up windows containing its tiny database of six images. The images were placed in the pages arbitrarily; the page has no input interface. Any single image can be popped up by placing its number in the text box next to the Image button and clicking the button. Figures 9.9 and 9.10 show the plain and framed versions of the image displayed in a catalog format. The image catalog is nothing more than a scrolling display of all the images in the database. Figure 9.8 The Image object can be activated to pop up an image database. Figure 9.9 The image database may be displayed as a scrolling window of plain images. Figure 9.10 The image database may be displayed as a scrolling catalog of framed images. Most of the draw methods presented here accept a string terminator as a parameter, and also return a string. The terminator is usually the carriage return character, \n. This results in a string with linebreaks suitable for an alert. You can also use <BR> as the string terminator; this yields a string that can be nicely presented in a window. The utility function showInWindow in Listing 9.25 pops up a window and tries to put anything you hand it into that window.

Listing 9.25 c9-image.htm--A Function that Shows an Object in a Pop-Up Window


function showInWindow(tstr,title) { var w = 300 var h = 300 scrl = `yes'

if (w>640){w=640;scrl='yes'} if (h>480){h=480;scrl='yes'} var whstr ='SCROLLBARS=' + scrl + `,RESIZABLE=yes,WIDTH=' + w + `,HEIGHT=' + h aNewWin = self.open(`',title,whstr) var astr = `<HTML><HEAD>' astr += `<BASE HREF="' + location.href + `">' astr += `<TITLE>' + title + `</TITLE>' astr += `</HEAD><BODY>' aNewWin.document.write(astr) aNewWin.document.write(tstr) aNewWin.document.write(`</BODY></HTML>') aNewWin.document.close() }

The Text Object


The approach we employed for the Image object can be used for text manipulation as well. We will create a Text object that holds various important properties related to how the text is displayed. This Text object will be very similar to the Image object in terms of the type of draw methods which it supports. The constructor function for the Text object is shown in Listing 9.26. All the code for the Text object will be found in the CD-ROM file c9-text.htm.

Listing 9.26 c9-text.htm--The Constructor Function for the Text Object


function createText(type,title,text,size,color,bold,italic, supersub,frame,href,notes) { this.type = type this.title= title this.text = text this.size = size this.color = color this.bold = bold this.italic = italic this.supersub = supersub this.frame = frame this.href = href this.notes = notes this.draw = drawText this.frame = frameText this.reference = referenceText this.popup = popText this.lines = stringToList this.word = word

return this } Notice that this function is very similar to the constructor for the Image object. It encapsulates some of JScript's own string properties. This object, too, knows how to present itself as plain, framed, or referenced text. It can also pop itself up in a window. Note that it has a type property; that is, the text can be a list, a paragraph, and so on. Its draw method accepts a parameter that allows you to draw the text according to a predefined type method or to draw the text using the properties you have set. The Text object has some methods that can access the text as lines or words. Again, this is a crude emulation of HyperCard. These methods allow you to define the separator which separates one phrase from another. The stringToList method accepts a prefix and a suffix as well as the list separator. It separates the string into phrases and then adds the prefix and suffix given. Use the \n character as the separator to get logical lines. Our old friend, the word() function, is used to return the word at the position you specify. The implementation of the stringToList method is shown in Listing 9.27.

Listing 9.27 c9-image.htm--A Function to Separate Delimited Strings into Phrases


function stringToList(sep, what, pref,suf) // sep = separator (delimiter) // what = object to use // pref = prefix to prepend // suf = suffix to append { var n = 0 // location of current separator var f = 0 // location of next separator var astr = `' // string being built var nstr = `' // work string var finished = false if ( what == null ) what = this while (f >= 0 ) { // get position of next separator f = what.indexOf(sep,n) // if this the last one? if (f == what.lastIndexOf(sep)) { // if so then get the end of the string f = what.length // and set the finished flag finished = true

} // get the string, prepend the prefix and append the suffix nstr = pref + what.substring(n,f) + suf // add the current working string onto the final string astr += nstr // if all done then break out of the loop if (finished ) break // advance to the next separator n = f + 1 } return astr // return the completed string } Note that this function uses an interesting trick to decide when it has come to the end of the string. It uses lastIndexOf() to get the character position of the last occurrence of the separator. As it walks the string, it checks to see whether the character found equals the last instance of that character. If it does, it sets the phrase end to the end of the string, performs its usual string separation, and then quits. Another useful routine, which can easily be modified for your own purpose is the makeTitle method. MakeTitle goes through a string and eliminates spaces, but capitalizes the letter after the space. This is useful for catching two-word window names, such as "Hi there," that a user has entered. If you hand the open() command more than one word, it simply does not open the window, nor does it tell you why. The makeTitle method converts such strings into more acceptable titles, such as "HiThere" in this case. The makeTitle function is shown in Listing 9.28. Figure 9.11 shows the result of exercising the pop-up capabilities of the Text object.

Listing 9.28 c9-text.htm--A Function to Create Window Title Strings


function makeTitle(what) { var n = what.length // length of string "what" var i = 0 // iteration variable var cc = `' // current character var accstr='' // output string being built for (i = 0 ; i < n ; i++) // iterate over the whole string { // get character at position "i" cc = what.substring(i,i+1) // if that character is not a space, then add it to the output string if ( cc != ` ` ) { accstr += cc continue

} else { // if that character is a space then skip it i++ // grab the first character after the space cc=what.substring(i,i + 1) // convert it to uppercase cc = cc.toUpperCase() // add that uppercase letter onto the output string accstr += cc } } return accstr // return the output string } Figure 9.11 The database of text objects can display itself in pop-up windows.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Chapter 12 Scripting and ActiveX


q

Scripting and ActiveX r Getting Microsofts ActiveX Controls s Label Control s Preloader Control s Timer Control s Menu Control r Inserting Controls with the OBJECT Tag s The OBJECT Tag in Detail s Setting a Controls Properties with the PARAM Tag r Connecting Controls to Scripts s Handling an Event s Changing an Objects Properties r Tying It All Together with an Example

Scripting and ActiveX


In this chapter you'll learn
q q q

What is an ActiveX control? Inserting controls in your Web page is easy Interact with ActiveX controls using JScript

An example of ActiveX controls You use ActiveX controls (the objects formerly known as OLE controls or OCXs) to insert a variety of functionalities into your Web page. For example, you can add a Timer control to your Web page that periodically updates the page's content, or you can use a Popup Window control to display tooltip-style help when the user holds the mouse pointer over a link. Considering that there are over a thousand ActiveX controls available for you to use, the possibilities are just about endless. Simply dropping ActiveX controls onto your Web page isn't enough if you want to build dynamic and exciting Web pages. You have to make all those controls work together. That's where JScript comes in. You associate scripts with the events and values of the controls you put on a Web page so that you can make them interact. You can update the contents of a TextBox control when the user clicks a button, for example, or you can open a Web page in a frame when the user chooses an item from a Popup Menu control.

TIP: Netscape Navigator can display ActiveX controls too. You need to get the ActiveX plug-in from Ncompass Labs, however. Open http://www.ncompass.com in your Web browser for more information.

Getting Microsofts ActiveX Controls


Microsoft provides a collection of ActiveX Controls with Internet Explorer 3.0. You don't have to do anything other than install Internet Explorer 3.0 to get them. Microsoft does package some controls only with the complete installation of Internet Explorer 3.0, though, and Microsoft provides other controls through its ActiveX Gallery Web site at http://www.microsoft.com/activex/gallery. Table 12.1 briefly describes each control and how you get it. The sections that follow show you real, live examples of some of these controls. Table 12.1 Microsoft's ActiveX Controls Name Provided by the Minimum, Typical, and Complete Installs of Internet Explorer 3.0 Web Browser Timer Marquee Provided by the Complete Install of Internet Explorer 3.0 ActiveMovie HTML Layout Forms 2.0 Label Forms 2.0 Textbox Forms 2.0 Combo Box Forms 2.0 List Box Forms 2.0 CheckBox Forms 2.0 Option Button Forms 2.0 Toggle Button Displays streaming and nonstreaming video and audio Displays 2-D HTML regions created with the ActiveX Control Pad Displays a text label Prompts the user for text Displays a drop-down list of options Displays a scrollable list of options Displays a checkbox option Displays an option button Displays a button that the user can toggle on and off Displays HTML files, ActiveX Controls, and ActiveX documents Executes a script at specific intervals Scrolls an HTML file horizontally or vertically Description

Forms 2.0 Command Button Forms 2.0 Tabstrip Forms 2.0 ScrollBar Forms 2.0 Spin Button Image Hotspot Provided at http://www.microsoft.com/ activex/gallery Animated Button Chart Gradient Label Menu Popup Menu Popup Window Preloader Stock Ticker View Tracker

Displays a basic button Displays multiple pages of controls that the user selects by clicking a tab Displays vertical and hortizontal scroll bars Displays a spin button that can be pushed up or down Displays a progressive image from a JPG, GIF, or BMP file Adds a transparent hotspot to a layout

Displays an AVI file on a button Draws various types of charts Shares an area with a range of colors Displays a text label with a given angle, color, and font Displays a button that pops up a standard menu that fires an event when the user chooses an item Displays a pop-up menu that fires an event when the user chooses an item Displays an HTML file in a pop-up window Downloads the file at the given URL into the user's cache Displays data from a text file at regular intervals Fires events when the control enters or leaves the browser's viewing area

NOTE: Many of the ActiveX controls you find on the Internet aren't digitally signed. By default, Internet Explorer 3.0 won't install unsigned controls--it doesn't even give you the chance to override it. Thus, Internet Explorer will ignore many of the controls that the Web page authors are using. Check your security configuration to make sure you have a choice: choose View, Options from the main menu; click the Security tab; click the Safety Level button; and make sure that you select Medium. Then Internet Explorer 3.0 will ask you before installing an unsigned control. If you choose not to install the control, the Web page may not work as the author intends. On the other hand, if you do install the control, you open yourself up to troubles that come from running controls from unknown sources, such as bugs that can cause the browser to

crash or, worse, controls that damage your system.

Label Control
The ActiveX Gallery shows an example of the use of the ActiveX Label control, shown in Figure 12.1. Using this control, you can display text within a Web page using any installed font, with any style or color, and at any arbitrary angle you choose. In this example, the two regions change--either color, text, or orientation--whenever you click them. Figure 12.1 The Label control gives you the ability to place text on the Web page without resorting to graphics.

Preloader Control
The ActiveX Preloader control makes your Web site seem faster than all the rest. You use it to speed up the apparent throughput of a Web session by allowing Internet Explorer 3.0 to cache graphics, video, and audio for a subsequent Web page while the user is looking at the current page. Normally, you'd use the Preloader control to quietly preload images or other HTML elements while the user is reading the current Web page. Then, when you want to go on to the next page in the Web site, or when you want to view an image file, hear a sound, or watch a video clip, Internet Explorer has already downloaded it to the cache and the user can view it without any further delay. You can see an example of the Preloader control at Microsoft's ActiveX Gallery.

Timer Control
The Timer control lets you periodically run a script that you can use to change the content of a Web page or perform some other task. Figure 12.2 shows a Web page that uses a timer to change the size and color of the two labels (each implemented with the Label control) over time. Both labels change at different intervals because this Web page uses two different Timer controls. Figure 12.2 You use the Timer control to execute a script at preset intervals, such as every second or every 10 seconds.

Menu Control
You use the Menu control to put a button on your Web that, when clicked by the user, displays a menu. When the user chooses a menu item, the control fires an event that you can handle with a script. Figure 12.3 shows you the example from Microsoft's ActiveX Gallery. It contains two Menu controls; each one displays a different submenu. Figure 12.3

You can use the Menu control to add menu-driven navigation to your Web site, like Microsoft's Site Builder Workshop.

Inserting Controls with the OBJECT Tag


You've seen the controls; now you need to know how to insert them into your Web pages. You use the OBJECT tag to do just that. With regard to ActiveX controls, the OBJECT tag identifies the control you're using. That's all. In the following sections, you dive into a detailed discussion of each of the OBJECT tag's attributes. Before that, however, take a brief look at how you use the OBJECT tag in a Web page. In its simplest form, the OBJECT tag looks something like the following: <OBJECT classid="clsid:1A771020-A28E-11CF-8510-00AA003B6C7E" id=Track1 width=400 height=2 align=left> <IMG SRC="noobject.gif"> <PARAM NAME="Image" VALUE="image.gif"> </OBJECT> The classid attribute uniquely identifies, on the computer, the control you're using. In this case, I'm using the View Tracker control. Don't let that awkward looking number throw you, it just identifies the control. You'll learn how to set this attribute later. You use the id attribute to identify the control to the scripts in your Web page. width, height, and align work the same as always. The OBJECT tag provides a way out for those browsers that don't support the OBJECT tag. Browsers that do support the OBJECT tag ignore anything between <OBJECT> and </OBJECT> that isn't a PARAM tag (you'll learn about this later). Browsers that don't support the OBJECT tag will ignore it and the PARAM tags and use the sandwiched tags instead. In this case, if the user's Web browser supports the OBJECT tag, she'll see the View Tracker control inserted into her Web page. Otherwise, she'll see an IMAGE.GIF image inserted using the IMG tag.

The OBJECT Tag in Detail


The OBJECT tag has a number of attributes that can be specified. Table 12.2 goes through each attribute and explains how you'll be using these attributes working with ActiveX controls. Use Table 12.2 as a quick reference for the OBJECT tag's attributes. The sections that follow describe each attribute in detail. Table 12.2 OBJECT Tag Attributes

Attribute ALIGN BORDER CLASSID

Description Determines placement of the object relative to other items on the page or relative to the page itself Specifies the width of the border to be placed around the object when used as an anchor URL that identifies an implementation of the object to be rendered on the page (i.e., a class identifier)

CODEBASE URL that specifies the location of the objects code (Java and ActiveX objects require this attribute) CODETYPE Internet Media Type for code that specifies the type of code that the CLASSID attribute refers to DATA DECLARE HEIGHT HSPACE ID IDMAP NAME STANDBY TYPE USEMAP VSPACE WIDTH URL that specifies the location of the objects data Indicates whether the object referred to in CLASSID is to be declared (and not loaded) or instantiated (loaded) Suggests the height that the Web browser should provide for display of the object Area to be preserved as white space to the left and right of the border and display space of the object A document-wide identifier for referring to the object Indicates that the object has a server-side image map Used to indicate whether the object's value should be included in a form submit Identifies the text to be displayed while the object is being loaded Refers to Internet Media Type (RFC 1590) for data URL for a client-side image map Area to be preserved as white space above and below the border and display space of the object Suggests the width that the Web browser should provide for display of the object

ALIGN.You'll use the ALIGN attribute to determine the placement of your ActiveX control in the Web page. ActiveX objects can be placed as part of the current text line or as a distinct element aligned left, right, or center. You'll set the ALIGN attribute to one of the values found in Tables 12.3 or 12.4, depending on the appearance you want to achieve. Table 12.3 Values for the ALIGN Attribute Relative to the Current Text Line Value TEXTTOP MIDDLE Meaning The top of the object is aligned with the top of the current font The middle of the object is aligned vertically with the baseline

TEXTMIDDLE The middle of the object is vertically aligned with a position halfway between the baseline and the height of the letter x in lowercase

BASELINE

The object's bottom is aligned with the baseline of the text line on which it appears Table 12.4 Values for the ALIGN Attribute as a Freefloating Object

Value LEFT RIGHT

Meaning The object will be placed on the left margin below the previous text or object in the page The object will be placed on the right margin below the previous text or object in the page

CENTER The object will be placed midway between the left and right margins

The ALIGN tag is currently fully implemented in Internet Explorer 3.0. BORDER. If the object is part of a hypertext link, the BORDER attribute suggests the width to be used as a border around the object's visible area. For instance, if you wanted the object to have no border at all as a hypertext link, you would set BORDER=0. The BORDER tag is currently fully implemented in Internet Explorer 3.0. CLASSID and CODEBASE CLASSID. are used to refer to the ActiveX control to be placed within the object's borders. There are several different ways to indicate the object to be executed here. ActiveX uses the clsid: URL scheme to specify the ActiveX class identifier. For further information on the clsid: URL scheme see http://www.w3.org/pub/WWW/Addressing/clsidscheme. The best way to obtain the CLSID for an ActiveX control is to look at the control's documentation. You can look up Microsoft's ActiveX controls at Microsoft's ActiveX Gallery. Alternatively, use the ActiveX Control Pad to insert an ActiveX control in your Web page so that you don't have to worry about the CLSID (see Chapter 19, "The ActiveX Control Pad").

Getting a CLASSID from the Registry You can also get the CLASSID for an ActiveX control from the Windows Registry, like this: Open the Registry Editor. Choose Run from the Start menu, type regedit, and press Enter. Locate a control under HKEY_CLASSES_ROOT, such as Internet. Gradient or Internet.Label. Note the default value of the CLSID subkey for that control. This is the string you use in the CLASSID attribute. You can learn more about CLSIDs in Special Edition Using the Windows 95 Registry or Windows 95 Registry Handbook by Que.

If the CLASSID attribute is missing, ActiveX data streams will include a class identifier that can be used by the ActiveX loader to find the appropriate control. The CODEBASE attribute can be used to provide a URL from which the control can be obtained. CODETYPE. The CODETYPE attribute is used to specify the Internet Media Type for the code

pointed to by the CLASSID attribute. Browsers use this value to check the type of code before downloading it from the server. Thus, the browser can avoid a lengthy download for those objects that it doesn't support. Currently, the CODETYPE attribute is supported in a limited fashion in Internet Explorer 3.0. Microsoft has indicated that TYPE will be implemented for all relevant MIME types. DATA. The DATA attribute contains a URL that points to data required by the object, for instance a GIF file for an image. Internet Explorer 3.0 currently supports the DATA attribute. DECLARE. You'll use the DECLARE attribute to tell the browser whether to instantiate the object or not. The DECLARE attribute indicates that the object should not be instantiated until something references it. That is, the browser will note the declaration of the object, but won't actually load it until you reference it. At this writing, the DECLARE attribute has not been implemented in Internet Explorer 3.0. However, Microsoft indicates that DECLARE will be supported. HEIGHT. The HEIGHT attribute suggests the height in pixels to make available to the ActiveX control when rendered by the browser. The Web browser may (or may not) use this value to scale an object to the requested height. The HEIGHT attribute is currently supported in Internet Explorer 3.0. HSPACE. The HSPACE attribute suggests the amount of space in pixels to keep as white space on the left and right as a buffer between the ActiveX control and surrounding page elements. The Web browser may (or may not) use this value to allocate white space. The HSPACE attribute is currently supported in Internet Explorer 3.0. ID. The ID attribute defines a documentwide identifier. This can be used for naming positions within documents. You also use the controls ID to reference it in scripts. The ID attribute is currently supported in Internet Explorer 3.0. ISMAP. The ISMAP attribute indicates that the Web server provides an image map. The OBJECT must appear within an anchor tag indicating a hypertext link in order for ISMAP to make sense. ISMAP requires that mouse clicks be sent to the server in the same manner as the IMG element is used for regular image maps. There is still disagreement among the W3C committee members working on the OBJECT tag definition, so the ISMAP attribute is not currently supported in Internet Explorer 3.0. However, Microsoft has indicated that ISMAP will be supported if it remains a part of the OBJECT tag specification. NAME. Use the NAME attribute to indicate whether an object wrapped in a FORM tag will be submitted with the form. If you specify NAME, the Web browser submits the VALUE property of the object to the host. If you don't specify NAME, the ActiveX control is assumed to be decorative and not functional in the form. The NAME attribute is currently supported in Internet Explorer 3.0. STANDBY. A short string of text can be displayed while the browser loads the ActiveX control. Use the STANDBY attribute to specify this text. The STANDBY attribute is not currently supported in Internet Explorer 3.0. However, Microsoft will likely implement this attribute. TYPE. The TYPE attribute is used to specify the Internet Media Type for the data specified by the

DATA attribute. You can learn more about Internet Media Types by referring to RFC 1590. You can get RFC 1590 from the Internet at ftp://ds.internic.net/rfc/rfc1590.txt. Currently, the TYPE attribute is supported in a limited fashion in Internet Explorer 3.0. Microsoft has indicated that TYPE will be implemented for all relevant MIME types. USEMAP. The USEMAP attribute is included for use with static images. The value in USEMAP specifies a URL for a client-side image map. The USEMAP attribute is not currently supported in Internet Explorer 3.0, but Microsoft has indicated that future versions of Internet Explorer will support USEMAP. VSPACE. The VSPACE attribute suggests the amount of space in pixels to keep as white space on the top and bottom as a buffer between the ActiveX control and surrounding page elements. The Web browser may (or may not) use this value to allocate the requested white space. The VSPACE attribute is currently supported in Internet Explorer 3.0. WIDTH. The WIDTH attribute suggests the width in pixels to make available to the ActiveX control when rendered by the browser. The Web browser may (or may not) use this value to scale an object to the requested width. The WIDTH attribute is currently supported in Internet Explorer 3.0.

Setting a Controls Properties with the PARAM Tag


You will need to set the properties of the ActiveX controls you put on the Web page in order to control its appearance or functionality. For example, you need to give the Stock Ticker control the URL of the text file it should use for data. You need to provide the Label control the text it should display. The only way to know for sure which properties each control requires is to check in the control's documentation. You can also use the ActiveX Control Pad to set a control's properties, as described in Chapter 19, "The ActiveX Control Pad." So how do you set these properties? You use the PARAM tag to assign a value to a named property within the control. This works very much like Visual Basic property sheets. Note that the PARAM tag has no closing </PARAM> tag. Table 12.5 describes the attributes you use with the PARAM tag. You frequently need to use only the NAME and VALUE attributes. Table 12.5 Attributes of the PARAM Tag Attribute NAME VALUE Description Defines the name of the property. Your ActiveX control can treat the name as casesensitive if desired Specifies the value of the property identified in NAME Refers to Internet Media Type (RFC 1590) of the item referred to in the VALUE field when VALUETYPE = REF

VALUETYPE Can be one of REF, OBJECT, or DATA TYPE

There is no need to go through all of these attributes--they are mostly self-explanatory except for the

VALUETYPE attribute. The VALUETYPE attributes are explained briefly in Table 12.6. Table 12.6 Values for the VALUETYPE Attribute Value REF OBJECT DATA Meaning Indicates that the value found in the VALUE attribute is a URL Indicates that the value found in the VALUE attribute is the URL of another OBJECT element Indicates that the value found in the VALUE attribute is intended to be passed to the OBJECT as a string; this is the default VALUETYPE

The following is an example of inserting an ActiveX control using the OBJECT tag. The CLASSID attribute specifies the Popup Menu control, and each PARAM tag adds a menu item to the menu. <OBJECT id=iemenu1 classid="clsid:0482B100-739C-11CF-A3A9-00A0C9034920" width=1 height=1 align=left hspace=0 vspace=0 > <PARAM NAME="Menuitem[0]" VALUE="First Choice"> <PARAM NAME="Menuitem[1]" VALUE="Second Choice"> <PARAM NAME="Menuitem[2]" VALUE="Third Choice"> <PARAM NAME="Menuitem[3]" VALUE="Fourth Choice"> <PARAM NAME="Menuitem[4]" VALUE="Fifth Choice"> </OBJECT>

Connecting Controls to Scripts


Now, we're getting to the meat of the matter. You've learned how to insert ActiveX controls into your Web page using the OBJECT tag. Now you need to learn how to interact with those controls using JScript. In the sections that follow, you'll learn how to handle the events that are fired by a control. You'll also learn how to get and set a control's properties from your scripts. ActiveX objects act like and quack like the elements on a form. That is, you interact with each ActiveX object's properties, methods, and events in exactly the same way in which you interact with a form's element. You handle an object's events when the object needs attention, you call an object's methods, and you get and set the object's properties.

Handling an Event

In Chapter 3, "Events and JScript," you learned all about events and event handlers. You can use a couple of different methods of handling events for forms and elements, but there's really only one way to handle an ActiveX control's events: using the FOR/EVENT attributes of the SCRIPT tag. The FOR and EVENT attributes let you associate a script with any named object in the HTML file and any event for that object. Take a look at the following: <SCRIPT LANGUAGE="JavaScript" FOR="btnButton" EVENT="Click()"> <!-window.alert( "Ouch! You clicked on me." ) --> </SCRIPT> <OBJECT ID="btnButton" WIDTH=96 HEIGHT=32 CLASSID="CLSID:D7053240-CE69-11CD-A777-00DD01143C57"> <PARAM NAME="Caption" VALUE="Click Me"> <PARAM NAME="Size" VALUE="2540;847"> </OBJECT> This defines a button (with an ID of btnButton) that executes the script when the user clicks it. Take a look at the <SCRIPT> tag. It contains the FOR and EVENT attributes that define the object and event associated with that script. FOR="btnButton" EVENT="Click()" says that when an object named btnButton fires the Click event, every statement in this script is executed. Some events pass arguments to the event handlers. How do you handle arguments when you're handling the event using the FOR/EVENT syntax? Like the following: <SCRIPT LANGUAGE="JavaScript" FOR="btnButton" EVENT="MouseMove (shift, button, x, y)"> The enclosed script can then use any of the parameters passed to it by the MouseMove event. TIP: Once you've specified a language in your HTML file, you don't need to do it again. Your browser defaults to the most recently used language used in the HTML file. You can put <SCRIPT LANGUAGE="JavaScript"></SCRIPT> at the very beginning of your HTML file one time and forget about it. The rest of the scripts in your file will use JScript.

You just saw the Click event. ActiveX controls support a wide variety of other events. The only way to know for sure which events a control supports is to consult the control's documentation or the ActiveX Control Pad's documentation. For your convenience, however, the following list describes the most prevalent and useful events:

q q q

q q q q q q q q q

BeforeUpdate occurs before data in a control changes. Change occurs when the value property in a control changes. Click occurs when the user either clicks the control with the left mouse button or selects a single value from a list of possible values. DblClick occurs when the user clicks twice with the left mouse button rapidly. DropButtonClick occurs when a drop-down list appears or disappears. KeyDown occurs when a user presses a key. KeyUp occurs when a user releases a key. KeyPress occurs when the user presses an ANSI key. MouseDown occurs when the user holds down a mouse button. MouseUp occurs when the user releases a mouse button. MouseMove occurs when the user moves the mouse pointer over a control. Scroll occurs when the user changes a scroll bar.

Changing an Objects Properties


Many objects let the user input data. What good are those objects if you can't get and set their value, then? You read the value of most elements using the object's value property, as follows: str = txtTextBox.value You can also set the value of an element by assigning a string to the element's value, as follows: txtTextBox.value = "New Contents of the Text Box" The value property is the default property for most ActiveX controls that accept user input. Thus, you can use them in an expression without explicitly using the value property, as follows: alert txtTextBox txtTextBox = "New Contents of the Text Box"

Tying It All Together with an Example


You've learned a lot in this chapter. You learned about the variety of ActiveX controls you can put in your Web page. You learned about using the OBJECT and PARAM tags to insert controls in your Web page. You also learned how to associate scripts with controls. An example might make things clearer for you, however, so that's exactly what you'll do in this section: Work through a quick example. This example in particular is a simple Web page that prompts the user for his name, and displays a greeting to him when he clicks a button. Use these steps to create this example: 1. Start with an empty HTML file. All you really need in this file are the <HTML> and </HTML> tags.

2. Insert a TextBox control called txtName into your Web page using the following OBJECT tag. You don't need to set any properties for the text box. <OBJECT ID="txtName" WIDTH=160 HEIGHT=24 CLASSID="CLSID:8BD21D10-EC42-11CE-9E0D-00AA006002F3"> </OBJECT> 3. Insert a Command Button control named cmdDisplay into your Web page using the following OBJECT tag. The Caption property determines what the user sees on the button. The Size attribute determines the size of the button. The ParagraphAlign property aligns the caption in the middle of the button, because it's set to 3. <OBJECT ID="cmdDisplay" WIDTH=60 HEIGHT=24 CLASSID="CLSID:D7053240-CE69-11CD-A777-00DD01143C57"> <PARAM NAME="Caption" VALUE="Display"> <PARAM NAME="Size" VALUE="2455;846"> <PARAM NAME="ParagraphAlign" VALUE="3"> </OBJECT> 4. Add the following script to the HTML file. The FOR attribute associates this script with the cmdDisplay object you created in step 3. The EVENT attribute associates this script with the Click event of the Command Button control. When the user clicks the button, Internet Explorer executes every line in this script, which displays a message box with the user's name in it. <SCRIPT LANGUAGE="JavaScript" FOR="cmdDisplay" EVENT="Click()"> <!-window.alert( "Hello " + txtName) --> </SCRIPT> 5. Save the HTML file and open it in Internet Explorer 3.0. Type your name in the text box, and click the button. You should see a message box similar to Figure 12.4. Figure 12.4 The user can't interact with Internet Explorer 3.0 as long as the message box is displayed.

NOTE: You've punished yourself enough--you've inserted a few ActiveX controls into a Web page by hand. Although you can continue to work with ActiveX controls by hand, I don't recommend that you do so. Microsoft's ActiveX Control pad makes inserting ActiveX controls into a Web page far too simple for you to continue whacking yourself with the OBJECT tag. See Chapter 19, "The ActiveX Control Pad," for more information.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Chapter 14 Controlling Web Page Appearance


q

Controlling Web Page Appearance r Page Building with JScript s Even the First Page Can Come Alive s First Page as a Control Panel s JScript-Enhanced Pages as an Application s Storing Control Panel Information s Good Design r Text Properties and Color Values s Text Properties s Color Values s Practical Uses of Text Properties s Overriding fgColor r Fonts and Font Methods s Description of Font Methods s Using Font Methods r Design of a JScript Message Editor s How the Message Editor Works s Layout Decision s Framing the Message Editor s Framesets Nest, Frame Objects Dont s HTML Code for a Layout r Program Structure or Coding the Events s Font Methods s messhelp.htm--Implementation of the Help Screen s The Preview

Controlling Web Page Appearance


q q q q q

JScript applications Storing data Color properties Designing a frame application JScript for text editing Hyperlinks as controls

As you are already aware, HTML is not desktop publishing. It provides structure and style to your Web page, but no control of the page width, size, or typography. This is what enables the Web to work on so many different platforms. Now, with JScript and recent extensions to the HTML specification, you have more control over page appearance. In fact, your whole site can almost be considered as one application. This chapter focuses on the appearance of text on your user's Web browser. The first section covers building JScript applications with a control panel. Next, text properties, font colors, and font methods are discussed. The chapter ends with a detailed example of a message editor, which uses all of the font methods of JScript.

Page Building with JScript


Before applying specific JScript properties, methods, and techniques, you must be aware of layout. This includes how the browser processes a page and its related documents, as well as some design principles about good layout. You can build multiple pages with JScript to design your application.

Even the First Page Can Come Alive


The first time a user requests a page from your site, the user has not yet given you any feedback, so you simply serve the page. When the page reaches the browser, however, the following two facts become available and can make the page come alive:
q

JScript-enhanced browsers can recognize code that other browsers will ignore. You can add a special welcome to your opening document that only JScript users can view. The code in Listing 14.1 makes a menu of links available only to JScript users. JScript-enhanced browsers know the time of day and the date. Using this information, you can change the appearance of the page. Although this has limited application, it is still worth considering. For example, you can display holiday greetings. Listing 14.1 also contains code for a greeting based on the hour of the day. As an example, look at Katipodesign (http://ourworld.compuserve.com/homepages/tuckey/ kmain.htm) shown in Figure 14.1. Although the heading says, "JavaScript," we are using JScript to look at it in Internet Explorer.

Listing 14.1 JScript Only Greeting and Menu


<HTML><HEAD><TITLE>greeting.htm by Ray Daly</TITLE></HEAD> <BODY><H1>WTFIN: Where to Find it Now</H1> <SCRIPT LANGUAGE="JavaScript"> <!-- hidden from other browsers today=new Date() //..get data and time x=today.getHours() //..pull out the hours

document.write (`<H2>Welcome JScript Surfers</H2>') if (x<12) { document.write(`<H3>Good Morning!</H3>') } else { document.write(`<H3>Hello on this beautiful day!</H3>') } //...you could substitute graphics instead of text greetings. document.write(`<P>Hidden away for your use only are several applications:</P>') // Add your own application link(s) here document.write(`<OL><LI><A HREF="mypage.htm">Message Editor</A></ LI>') document.write(`<LI>More applications here.</LI></OL>') // all done with JScript--> </SCRIPT> <!-- Add you own forward link here --> <A HREF="mypage2page.htm">Continue to <I>Find it Now</I>.</A> </BODY></HTML> One of the first things you learn about JScript is that you cannot really change much about a page that is already displayed. Change a property, and most likely it doesn't change the display. The text and layout of form elements are fixed. You can, however, change the background color. For most pages, this may seem trivial, and it probably is. But you can be creative with this feature. This is covered in more detail later in the section, "Practical Uses of Text Properties."

First Page as a Control Panel


Although the user can't control the currently displayed page, data from this page can change the appearance and content of related documents. In many ways, you can consider the first page to be a control panel that enables the user to make choices that affect all related documents. As an example, you can create a frameset in which one frame is the "control panel." In this frame, the user can click a choice of font and background colors. The rest of the documents in the other frames are then displayed using this selection. Figure 14.1 Katipodesign shows how graphic design can be enhanced with JScript. But you have to visit it at different times of the day to see it all.

TIP: With frames, you have the frame document and related documents. You may not want the user to be able to load the related documents without the frameset. In these related documents, you can use the onLoad event handler to verify that the document

was loaded with the frameset.

The first page can also control content. For example, a sports site might start by asking which sports interest you. The rest of the site can omit links and information on teams and games that don't match your interest.

JScript-Enhanced Pages as an Application


These control panels could be more sophisticated to the point of becoming a full-fledged application. You might develop a whole series of questions, something like a registration page, and all subsequent documents could be modified by the registration data from the control panel. These control panels are coming up more and more often on sites (see Figure 14.2). It is possible to build very advanced JScript applications using this technique. The dependence on data from the first page is like a parent-child relationship. (This is very different from today's Web sites, in which most pages can stand on their own.) Although the server can send what appears to be static pages, the JScript in these pages makes them come alive in the browser. Figure 14.2 Dave's Tekno Dive (http://www.dream.com) gets better with each visit. If you register, he saves your background preference for 30 days. The control panel changes the way you browse his site.

NOTE: As you will see in this chapter, you can create documents that are only a part of an application. Often, these pages make little or no sense on their own. Yet, all pages look the same to a search engine. To discourage people from directly accessing these secondary documents, consider hiding these pages from the search engines. This is usually done with a ROBOTS.TXT file. When a search engine indexes a site, it uses a program called a robot or a spider. When the engine visits a site, the first file it reads is ROBOTS.TXT. Using the information in this file, the search engine's robot omits specified areas from its search on the site. Take a moment to read "A Standard for Robot Exclusion," which is available at http://info.webcrawler.com/mak/projects/ robots/norobots.html.

See "Frames and JScript," (Chapter 17, "Using Frames and Cookies") for more detail on frames.

Storing Control Panel Information


As you develop JScript applications, you will have multiple related documents. Sharing information

between these documents is part of the process of building these applications. But now that you have collected all of this information, you may want to start storing it. Cookies Store Information in the Browser. One means of storing information between pages is to use cookies (client-side persistent information). The browser, not the server, maintains this information. When using cookies, each time the browser makes a certain request to a server, the request includes this stored information. The server may or may not use this information. Let's look at a simple example. Say you want to store a customer's name, such as Smith. The information is stored by the browser, and when the browser requests another related page, this information is sent to the server by the browser. Cookie data uses the format NAME=VALUE. For this example, it would be customer=Smith. If you have multiple pairs of data, just separate them with semicolons--for example, customer=Smith ; phone=8005551212. To store information in a cookie with JScript, you can use the cookie property of the document. To store a value, use a statement like this: document.cookie = "customer=Smith" In the default mode, the cookie information is maintained until a session ends. Also, the information is sent only when requesting pages from the same server. More details are available in Netscape's Preliminary Specification (http://home.netscape.com/newsref/std/cookie_spec.html). You also retrieve information from the cookie by using the cookie property. Then, using string methods, you could extract the information. For our customer Smith example: var pair=document.cookie lastname = pair.substring(pair.indexOf("=")+1,pair.length) ///...lastname should now equal Smith You can store cookie information in two ways. First, as you gather important information, you might want to store it immediately in the cookie. The other method is to create an exit function. This function is called by an unLoad event, and saves the information into the cookie. While the cookie specification is considered preliminary, the standard is supported, to varying degrees, by a wide number of browsers, including Internet Explorer. So, while you should use it with some degree of caution, cookies will certainly become more common. URLs for Storage. Though this is infrequently used, you can store information in the URL for your page. Using the search property of a location, you can add text to the end of your URL. While extremely long URLs can cause server problems, storing small amounts of data should work flawlessly. Search data is the information after a question mark (?) in an URL. In the following example, ?info=htmljive is the search portion of the URL:

http://www.yoursite.com?info=htmljive After a user enters registration information, you can take him or her to a post-registration page. Have your code add registration information to the URL using the search property (see Listing 14.2). Recommend to the user that he or she make that page a favorite. This saves the user's registration information as part of the favorites list. When the customer returns to your site using the favorites list, you can read the search property of the URL. Now you have the registration information, and your user can be immediately directed into your site.

Listing 14.2 Store Information in an URL


<HTML><HEAD><TITLE>search.htm by Ray Daly </TITLE> <P>Save this page as a favorite to avoid the registration page on your next visit..</P> <script language="JScript"> if (location.search==""){ //...need this if control to avoid an endless loop window.location.search="?infohere" //..add information to URL document.write(window.location.href) } </script></HEAD><BODY></BODY></HTML> Most often, you will see search information stored in a format of associative pairs. In this format, you have field=value. Multiple pairs are separated by the ampersand (&), and spaces are not permitted. Go to almost any search engine and do a simple search. The page that is returned to you will have search text in its URL. For example: http://www.altavista.digital.com/cgi-bin/query? pg=q&what=web&q=htmljive Though the format of associative pairs is common, there appears to be no requirement to use them. I've found that you can put almost any text or numeric data you want into this portion of the URL. Parent Knows All. While cookies and favorites lists with search information allow user information to be stored between visits, you can also maintain information during the current visit using the control panel concept. JScript works with both frames and multiple windows. As long as a window from your application stays open, the browser can store data. For example, a user can work within your application and then hyperlink to another site. You can design all of your external links to open up new browser windows. This way, your original window is not unloaded, and your data is retained.

Good Design

Whether a Web page looks good is a matter of taste: What you like, others might avoid. This factor should be part of your design. Enable users to change the appearance of the page, even to a style that you yourself would not normally choose. For example, many people set their word processor to use vibrant colors, such as bright green and rich purple. This is a style others might use only occasionally, if at all. Although everyone has individual tastes, the following are various principles that can produce goodlooking pages (see Figure 14.3):
q q q q

Keep it simple: Focus the document on a topic. Leave white space: Don't fill your page with text or images (especially large ones). Employ only the styles you need: Don't use every option. Shorter lines of text are easier to read.

Figure 14.3 Almost everyone agrees that Yahoo!'s design is elegant and to the point. The graphic is all that is necessary and is functional. The text is easy to read in multiple columns with spacing between the lines.

Text Properties and Color Values


Background color and tiles have forever changed the Web. A site without a background is considered old-fashioned and behind the times. This puts a burden on the designer to be a color coordinator. If you change the background color, you also need to be able to modify the colors used to display text. Having the background color match the text color makes the text invisible. Although you might want to use this as an effect, most of the time you will want a pleasant contrast between these two colors.

Text Properties
There are five text properties available from the browser. These all reflect the values of the TEXT attribute of the BODY tag. The first two are the color for the background and for the text of the document. These properties are called bgColor and fgColor. The three other text properties reflect the three different colors applied to hyperlink text. Usually, you want your hyperlinks to stand out from the rest of the text. Although early browsers displayed these links by underlining the text, now most browsers distinguish these links by color. They also provide feedback to the user by changing this color momentarily when the user clicks the link. After a link is visited, the color is also changed. These properties are called linkColor, alinkColor, and vlinkColor, respectively. The syntax for these properties is as follows:

document.fgColor [= [<RGB Triplet> | <Color Name>]] document.bgColor [= [<RGB Triplet> | <Color Name>]] document.alinkColor [= [<RGB Triplet> | <Color Name>]] document.linkColor [= [<RGB Triplet> | <Color Name>]] document.vlinkColor [= [<RGB Triplet> | <Color Name>]] While <RGB Triplet> is a string of hexadecimal values representing a combination of the colors red, green, and blue; <Color Name> is a string representing a specific color's name as defined in the Color Table. See Appendix C for both the hexadecimal and the literal names for predefined colors.

Color Values
You specify the color for TEXT properties just as you would any other color element. The general syntax is: document.textproperty = "colorvalue" where colorvalue is either a hexadecimal or a literal name representing a color. Hexadecimal Values for Color. Prior to JScript, all color values were specified using the RGB hexadecimal values. This is a six-digit number. It is often called a triplet because it is divided into three sets of two digits each: The first two digits specify the amount of red, the second two the amount of green, and the last two the amount of blue. Because the numbers are hexadecimal, the values range from 00 to FF. (255 is the decimal equivalent of FF hexadecimal.) For example, black is FFFFFF and white is 000000. Aqua, which is an equal mix of green and blue, is represented by 00FFFF: document.fgColor = "00FFFF" Using Color Names. JScript provides another option besides hexadecimal numbers for specifying color values: You can use names. Instead of coding: document.fgColor = "0000FF" you can use the word blue like this: document.fgColor = "blue" You have a choice of over 150 predefined colors. Of course, you have standard colors such as blue, violet, cyan, and maroon. But now, such colors as dodger blue, tomato, Navajo white, Indian red, peach puff, and Alice blue are available directly from JScript. See "Color Values," (Appendix C) for a list of color names.

NOTE: You probably remember the primary colors: red, yellow, and blue. Why are the colors red, green, and blue used for computers? Why green instead of yellow? Red, yellow, and blue paints are commonly used on paper to learn about primary colors. In that case, white light reflects off the mixture of paints to produce the desired color. No paint produces white, and equal amounts of each color absorb all of the reflected light, producing black. The important point is the reflected light. The color you see is a result of reflected light. Red, blue, and green (RGB) are the primary colors when the light itself provides the color. It doesn't matter whether you mix red, green, and blue lights on a darkened theatrical stage or from inside a monitor or television. No light produces black; an equal amount of all lights produces white.

Color Tools. As you work with color, you will find that having a few tools will make things easier. For example, what is the hexadecimal number for light purple? What color text looks good on a coral background? A chart that shows the hexadecimal representation of a desired color is a great tool. There are numerous charts available. The RGB Hex Triplet Color Chart at www.phoenix.net/ ~jacobson/rgb.html is an excellent example. Whenever you need to see what a color really looks like, you can just load the page and see it displayed on the monitor. A program that actually lets you experiment with color properties and background tiles is hIdaho Design's Color Center&tm; (http://www.hidaho.com/colorcenter/) by Bill Dortch (see Figure 14.4). You select colors and actually see the results on your screen. Not only is it a great way to find pleasant color schemes, but it is also a brilliant JScript application.

Practical Uses of Text Properties


Knowing the text properties of the current document, you can use these values to set the text properties for any new documents. Make the new documents the same as the current one, or create a new color by manipulating the current property values. Another use is to provide feedback that the user's action was recognized. You can either replace the existing background or possibly flash the background. You can also use it with a countdown sequence like ticks of a clock. For example, upon a user's action, say clicking a hyperlink, you can make the background color change to the standard text color. This makes the text "disappear" and notifies the user that his or her action was accepted. The code for this example is in Listing 14.3 and can also be found on the CDROM as color16.htm. Figure 14.4 hIdaho Design's Color Center&tm; is even more brilliant on your monitor. You can work in hex, decimal, or percentage. The logo is an animated GIF file.

Listing 14.3 color16.htm--Changing Background Color


<HTML><HEAD><TITLE>color16.htm by Ray Daly</TITLE></HEAD> <BODY bgColor="red" fgColor="black" > <P>Simple example of changing background color.</P> <P><FONT COLOR="green">Why did the chicken cross the road?</P> <P><FONT COLOR="document.bgColor">To get to the other side.</P> <!--...make color same as background to make invisible --> <FORM><INPUT TYPE="button" VALUE="Red" onclick='document. bgColor="red" `> <INPUT TYPE="button" VALUE="Green" onclick='document. bgColor="green" `><BR> </FORM> <P><A HREF="http://www.yahooligans.com/" onClick='document.bgColor="black" `>Yahooligans</A> </BODY></HTML>

Overriding fgColor
Normally, the color specified with fgColor is the color of all the text on the page, except hyperlinks. You can override this color by using the fontcolor element. For example, you can place one paragraph of text in between <FONT COLOR="chocolate"> and </FONT>. The text of this paragraph would then be displayed in the color chocolate instead of the color specified by fgColor. JScript provides for a method for placing FONTCOLOR tags around a string. This is the topic of the next section.

Fonts and Font Methods


You have certainly used physical styles such as bold, fixed, and italics for your HTML pages. JScript has methods for these three styles as well as blink, strikeout, subscript, and superscript. It also has methods for big, small, fontsize, and fontcolor. This chapter groups these methods under the name of font methods.

Description of Font Methods


The result of a font method places the appropriate tags at the beginning and end of the string. For example, for the physical style of bold, if testString="example", then the result of testString.bold() is <B>example</B>. In other words, the result of a font method is a new string with HTML code embedded in it. Following you will see three figures that demonstrate all the JScript font methods. Listing 14.4 shows

the use of each font method on the same string. Listing 14.5 shows the equivalent HTML code. Figure 14.5 is a screen shot showing the display of each style.

Using Font Methods


The font methods are useful in three primary ways, as follows:
q q

Your page can directly create a new document in a new window or a frame. Your page can collect a sequence of inputs, and build the new document only when the user signals completion. Your user can create an HTML document that is submitted to the server. The server can then save this page and make it available to other users. Your user may never see the new document.

Using Font Methods Directly. You create new documents using the document.write or document.writeln methods. As part of the string used in a document.write method, you can use the font methods instead of hard-coding in the style tags. See "Browser and HTML Objects," (Chapter 4, "JScript Objects"), for details on the document.write method. It can be easier to debug using document.write (promptstring.bold()) than document. write ("<B>" + promptstring + "</B>"). It also allows for the browser to handle implementation of HTML tags, since the specifications may change in the future. In the following example, you see the JScript code using document.write (see Listing 14.4), the equivalent HTML code (see Listing 14.5), and the display of that HTML code (see Figure 14.5). This code will be found on the CD-ROM in the files fontmeth.htm and FONTACTU.HTM. This shows the use of each of the different font methods. Figure 14.5 shows how either one of these documents will display on a browser. Because the HTML code does not actually specify a font, the results will vary depending on your browser preferences.

Listing 14.4 fontmeth.htm--All Font Methods in Use


<HTML><HEAD><TITLE>fontmeth.htm by Ray Daly</TITLE> <SCRIPT LANGUAGE="JScript"> var testString = "JScript Font Methods " document.write (`<P>') document.write (testString.bold()+"<BR>") document.write (testString.fixed()+"<BR>") document.write (testString.italics()+"<BR>") document.write (testString.blink()+"<BR>") document.write (testString.strike()+"<BR>") document.write (testString.sub()+"<BR>") document.write (testString.sup()+"<BR>") document.write (testString.big()+"<BR>") document.write (testString.small()+"<BR>") document.write (testString.fontsize(1)+"<BR>")

document.write (testString.fontsize(2)+"<BR>") document.write (testString.fontsize(3)+"<BR>") document.write (testString.fontsize(4)+"<BR>") document.write (testString.fontsize(5)+"<BR>") document.write (testString.fontsize(6)+"<BR>") document.write (testString.fontsize(7)+"<BR>") document.write (testString.fontcolor("FA8072")+"<BR>") document.write (testString.fontcolor("salmon")+"<BR>") document.write (`</P>') </SCRIPT></HEAD><BODY<</BODY></HTML>

TIP: You can combine font methods to act on one string. For example, to produce a bold, size 4 font in the color of salmon, use the following code:

testString.bold.fontsize(4).fontcolor("salmon")

Listing 14.5 fontactu.htm--Equivalent HTML Code to Font Methods


<HTML><HEAD><TITLE>fontactu.htm by Ray Daly</TITLE></HEAD><BODY> <B>JScript Font Methods </B><BR> <TT>JScript Font Methods </TT><BR> <I>JScript Font Methods </I><BR> <BLINK>JScript Font Methods </BLINK><BR> <STRIKE>JScript Font Methods </STRIKE><BR> <SUB>JScript Font Methods </SUB><BR> <SUP>JScript Font Methods </SUP><BR> <BIG>JScript Font Methods </BIG><BR> <SMALL>JScript Font Methods </SMALL><BR> <FONT SIZE="1">JScript Font Methods </FONT><BR> <FONT SIZE="2">JScript Font Methods </FONT><BR> <FONT SIZE="3">JScript Font Methods </FONT><BR> <FONT SIZE="4">JScript Font Methods </FONT><BR> <FONT SIZE="5">JScript Font Methods </FONT><BR> <FONT SIZE="6">JScript Font Methods </FONT><BR> <FONT SIZE="7">JScript Font Methods </FONT><BR> <FONT COLOR="FA8072">JScript Font Methods </FONT><BR> <FONT COLOR="salmon">JScript Font Methods </FONT><BR> </P></BODY></HTML> Figure 14.5 This is how the browser displays the HTML code for font methods (refer to Listings 14.4 and 14.5). The code is different but the results are the same.

Using Font Methods Indirectly. There may be many cases in which you want to build a document as user inputs are gathered, instead of immediately. This enables users to select components to be used for their documents. By putting the components together in different sequences, users create different HTML pages. Using an indirect technique, they can preview the page prior to finalizing it. A very practical example is an HTML editor (see Figure 14.6). The user builds the page using various form inputs, such as buttons. These activate functions that insert HTML tags using the font methods. As the user builds the page by making various choices, the raw HTML code is displayed in a textarea of a form. The textarea functions like a text editor in which the user can make changes prior to finalizing the document. In other cases, you may not want the user to be capable of directly editing the HTML code. Instead of building the HTML page in a textarea, you can use a hidden form element. Just use the value of that hidden element to store the code until it is ready to be directed to a new document (see Figure 14.7). The code for this example is in Listing 14.6, and will be found on the CD-ROM in hidden.htm. Figure 14.6 HTMLjive is an HTML editor written in JScript. You build a document in the textarea with the option to preview it. Figure 14.7 In this example, code is stored in the hidden form element, but you don't see it until you click the Show New Document button.

Listing 14.6 hidden.htm--Storing New Document in Hidden Value


<HTML><HEAD><TITLE>hidden.htm by Ray Daly</TITLE> <SCRIPT LANGUAGE="JScript"> <!-- hide code from other browsers function preview (form) { msg=open ("", "DisplayWindow","toolbar=yes,scrollbars=yes") msg.document.write(form.storage.value) } // end hiding --> </SCRIPT> </HEAD><BODY> <P>Demo of building a hidden HTML document. Click several times on the Holiday buttons before asking for a preview.</B> <FORM> <INPUT TYPE="hidden" NAME="storage" VALUE="<HTML><HEAD><TITLE>Greetings</TITLE></HEAD><BODY>"> <!--...this hidden element is where the HTML document is created --> <INPUT TYPE="button" VALUE="Happy Fourth" onClick='this.form.storage.value += "<H1>Happy Fourth</H1>" `> <INPUT TYPE="button" VALUE="Happy Halloween"

onClick='this.form.storage.value += "<H1>Happy Halloween</H1>" `> <INPUT TYPE="button" VALUE="Show New Document" onClick="preview (this.form)"> </BODY></HTML> HTML Strings as a Submission. There is also the case in which the new HTML code is never directly displayed by the browser. Instead, using the various user inputs, the HTML code is stored either in a text box or in a hidden value. When complete, the resulting code is submitted to the server that processes it. A practical example is a Web-based message board. Users can compose messages using a JScript-enhanced message editor. Because the messages become part of a Web page, they contain various physical styles, such as bold and italics. Buttons can be part of the form, so users do not necessarily need to know the HTML code to add italics or bold to their messages. When a message is complete, it can be sent to the server and appended to an existing page. Another example is a salesperson's weekly report. A salesperson can complete a Web form about his or her activity. This might include invoice numbers, dollar amounts, and comments. When the report is complete, the JScript code adds HTML code to the various inputs. The final document is submitted to the server, where it is simply appended to the sales manager's page for his or her review on Monday morning.

Design of a JScript Message Editor


For a detailed and practical example, we will build a message editor. This JScript- enhanced page provides controls for the user easily to add HTML style tags to messages. This final text is then submitted to a server, where the message is added to a guest book, a message board, or any other site that accepts HTML-enhanced messages. Designing JScript applications often works best if you lay out the interface first. This is a way to decide not only the layout, but the events for which you need to write code. Once you have the layout, then write the code that works behind each event. This is a common technique for eventdriven programs, and it is the approach taken for our message editor. CAUTION: The initial release of JScript has limited methods available for text editing. First, the string methods are limited. For example, there is no search and replace method. The other limitation relates to the fact that text editing takes place in a textarea. The textarea object has no properties related to the cursor position. Therefore, text functions can append new text only to the end of the text, and not at the cursor. Despite these limitations, interesting applications can be created.

How the Message Editor Works


This application basically works like any other page with a text box in a form. The users complete

their information, and they can edit it. When it is finalized, the text is submitted to a server where it is processed. JScript enhances this process. We will design a control panel in which the user can select a text style. The program will then prompt the user for the text to highlight with a style. After the user has finished typing, the text and the HTML code are appended to the message in the text area. The other main feature of the message editor is the preview window. Users will be able to preview their HTML documents prior to submitting them to the server. This will be activated by a button on the control panel. Because all of this activity takes place in the browser (on the client side), the load on the server is reduced. It also provides a much quicker response time than waiting for the server to return a previewed document.

Layout Decision
You must decide whether to create this application in one document or multiple documents. There are trade-offs with either choice. You can make one long document with all of the HTML and JScript code. The user may then need to scroll around the page to use it. This choice can also be easier to code. The real benefit is that the user can save and recall the application in a single file on his hard drive. The other option is to create one frame for the control panel and another for the text window. Users will not be able easily to save the application on their hard drives because it is now in several files, but the real benefit is ease of use, because the user will not have to scroll around as much. For our example, we will use a page with frames. There will also be a dialog box and two other windows.

Framing the Message Editor


For the message editor, there are two main frames. The top frame displays the control panel. It is as wide as the browser allows, and it has a fixed height large enough to contain all of the controls. The top panel is subdivided into a left and right section. The left simply displays the last font color used. This is a fixed width. The right contains all of the controls, and extends to the edge of the screen. The second frame will contain the text box. This is where the message is edited. Like the other frame, the width is the same as the screen. Its height is variable, taking up the remainder of the vertical space. Listing 14.7 is the code for creating the frames (file messedit.htm on the CD-ROM). To test the frames, three test documents are created (see Listings 14.8, 14.9, and 14.10). These documents will be modified as we develop the application. Our test result is shown in Figure 14.8.

Listing 14.7 messedit.htm--Frameset Document for Message Editor


<HTML><HEAD><TITLE>Message Editor by Ray Daly</TITLE> <FRAMESET ROWS = " 110, * "> <FRAMESET COLS="20,*"> <!-- this is the upper frame, divided into two more frames --> <FRAME NAME="messcolr" SRC="messcolr.htm"> <FRAME NAME="messcont" SRC = "messcont.htm"> </FRAMESET> <FRAME NAME="messarea" SRC="messarea.htm"> <!-- this is the lower frame --> </FRAMESET> </HTML> Using frames with Internet Explorer requires multiple documents. The primary document is a new type of HTML document because it has no <BODY>. Instead, the document uses the FRAMESET element. The contents of the FRAMESET tag are FRAME tags. The primary attribute of the FRAME is the source document, which is displayed in the frame. So, for a page with two frames, you would have two FRAME elements, each specifying a source document. The subsidiary files for the FRAMESET shown in Listing 14.7 will be found as messcont.htm, messarea.htm, and messcolr.htm on the CD-ROM. One other optional element of a FRAMESET is another FRAMESET. You would use this in the case where you want to subdivide a frame into different frames. This is how we create the message editor example.

Listing 14.8 messcont.htm--Test Document for Upper Frame


<HTML><HEAD><TITLE>Message Editor by Ray Daly</TITLE> <BODY bgcolor ="white"> <H1>messcont.htm</H1> </BODY></HTML>

Listing 14.9 messarea.htm--Test Document for Lower Frame


<HTML><HEAD><TITLE>Message Editor by Ray Daly</TITLE> <BODY bgcolor ="white"> <H1>messarea.htm</H1> </BODY></HTML>

Listing 14.10 messcolr.htm--Test Document for Color Frame


<HTML><HEAD><TITLE>Message Editor by Ray Daly</TITLE> <BODY bgcolor ="black">

</BODY></HTML> Figure 14.8 It's always a good idea to test your frames to see whether they are the size you expect.

CAUTION: Internet Explorer will cache frame information, if possible. If you modify the frame dimensions and just reload, this does not always change the frame sizing. To be certain, you may have to load a different page and then reload your page.

Framesets Nest, Frame Objects Dont


The message editor contains a set of nested framesets. The primary, or top, frameset contains another frameset. This is done to subdivide a frame into two other frames. You might think of these frames and framesets as a tree structure. Using the filenames from our example, a tree might break down to resemble the following: Frameset: MESSEDIT.HTM Parent Child Frame: MESSTEXT.HTM Frameset: Child Grandchildren? Frame: MESSCONT.HTM Frame: MESSCOLR.HTM Because the top file is considered the parent by JScript, you would consider messtext and the Frameset to be children. So, the other two frames would be considered grandchildren, right? Surprisingly, the answer is no! When JScript creates the objects from the framesets, all of the frames get "flattened." In other words, each frame, regardless of how deeply it is nested, is considered a child and is placed into the same frame array. All frames are placed into the array in the same sequence that they appear in the HTML file. All nesting is ignored, for example: frames[0].document.name is messcolr frames[1].document.name is messcont frames[2].document.name is messarea This makes it easier to properly refer to a property in another frame. You don't need to know the relative relationship between frames, since they are each a child to the parent. If we were to add a textarea (called messaret) in a form (called heavy) in a frame (named messarea) from a function in the other frame (called messcont), then we could reference the contents of this textarea using:

parent.messarea.document.heavy.messaret.value Please note the word document in this code. Since a frame has several properties, you must specify that you are referring to the document property.

HTML Code for a Layout


In deciding on a layout, we will provide just enough code to see what the application will look like. For the textarea, no further coding is needed other than layout. For the control panel, we will display the various buttons and other controls with practically no JScript coding. HTML Code for the Textarea. This frame will consist primarily of a form. You can also select a background color for the form elements to sit on. There will also be one line of instruction at the top of the textarea. As defined by the frame coding above, this document is called messarea.html. Let's start with the standard tags and define the background color as aqua: <HTML><HEAD><TITLE>Message Editor by Ray Daly</TITLE></HEAD> <BODY bgcolor="aqua"> Next is the start of the form and the single line of instruction: <FORM NAME="heavy"><P><B>Type your message in this box:</B><BR> This form will contain only three elements. The first element of the form is the textarea: This one is defined with a column width of 70 and a height of 16 lines. You can make these whatever dimensions you choose.

TIP: You can choose a text area that is longer than the frame. Then, the user will have to scroll the frame to get to the Submit and Reset buttons. In this case, you might consider putting one set of buttons at the top of the textarea and another at the bottom. This is a design choice.

The coding of the textarea follows the standard format. There is also an attribute of wrap=virtual: <TEXTAREA NAME="messtext" ROWS="10" COLS="70" WRAP="virtual"> </TEXTAREA>

NOTE: The TEXTAREA element has a tag called WRAP. There are three different options for this tag, as follows: off--This is the default setting. There is no wrapping;

lines are sent exactly as typed. virtual--With this option, the display is word-wrapped, but the actual text is not. In other words, you see a long line wrapped, but the browser sends it as one long line to the server. physical--With this option, the display is wordwrapped and the text is sent with all wrap points. The syntax is:

<TEXTAREA WRAP="wrapvalue"> The final two elements are the buttons for submitting the document and an optional Reset button. The default wording is not used. Because this program is like a word processor or text editor, those types of terms are used: <INPUT TYPE="submit" VALUE="Submit Message"> <INPUT TYPE="reset" VALUE="Reset: Erase all text"> To finish this document, we need to only close the tags for both the FORM and HTML: </FORM> </HTML> The code for this entire document is shown in Listing 14.11. Figure 14.9 shows how this document looks inside our frame. This file is included as messare2.htm on the CD-ROM. You should copy it to your hard drive and rename is as messarea.htm in order for the top level Frameset to reference it correctly.

Listing 14.11 messare2.htm--Text Area in Lower Frame


<HTML><HEAD><TITLE>Message Editor by Ray Daly</TITLE></HEAD> <BODY bgcolor ="aqua"> <FORM NAME="heavy"><P><B>Type your message in this box:</B><BR> <TEXTAREA NAME="messaret" ROWS="10" COLS="70" WRAP="virtual"> </TEXTAREA> <INPUT TYPE="submit" VALUE = "Submit Message" > <INPUT TYPE="reset" VALUE = "Reset: Erase all text"> </BODY></HTML> Figure 14.9 Notice the large message area waiting for a user to type something. The wrap attribute is set to virtual to force word-wrapping. You can add another button to this frame, as users might appreciate having a Preview button right next to the Submit button. This button allows users to preview their messages prior to submitting them. The Preview button is detailed in the section, "The Preview," later in this chapter. At this point, three of the four documents that make up the message editor are complete. The main

code is in the control panel, which we will now develop. The Controls in the Control Panel. The control panel will have three rows of controls. These controls prompt the user for text to be appended to the text in the textarea with the appropriate HTML codes. The first row will contain eight buttons, all of approximately the same size. These buttons are for the physical styles: bold, italics, fixed, strike, blink, sup, and sub. (The buttons will display these words.) There will be an eighth button on this row called About. The second row will contain nine controls. The first two buttons are of the same size as those in the first row. These are for the styles big and small. Then there will be much smaller buttons for font sizes 1 to 7. The last button on this row will be for Help. The third row is a set of seven hyperlinks. The text for these are eight standard colors, except white. Each text will be displayed in its corresponding font color. The last control on the row will be a button for the preview feature. Putting the Controls into a Table. The controls should appear properly spaced to make it easier for the user to find the button he or she wants. Aligning the buttons also makes it easier on the eyes. To accomplish the desired layout of these controls, each will be centered within a cell of a table. The <TABLE> is being used only for layout purposes and has no borders. It will be effectively invisible to the user. Given three rows of controls, the table will also have three rows. With both the top and bottom rows having eight controls, we know the minimum number of columns is also eight. Because the middle row has several smaller buttons and a total count of ten, we are going to double the number of columns to sixteen.

Tip: Centering buttons within cells of a table hides the fact that the buttons are different sizes.

The standard size buttons--those from the top and bottom rows--will be placed in cells that span two columns. The seven smaller buttons for font sizes in the second row will each be placed within single cells. The coding for this table is in Listing 14.12. There are comments inserted into the cells where coding will go for each control. Also, the entire table is between FORM tags, because each button is a form element. The standard elements that define an HTML document are also there, including a background color of light gray.

Listing 14.12 Tabled Layout of Controls


<HTML><HEAD><TITLE>Message Editor by Ray Daly</TITLE> </HEAD><BODY bgcolor ="white">

<TABLE WIDTH="100%" HEIGHT="100%" BORDER="0"> <TR><TD COLSPAN=2><!--bold here-->bold</TD> <TD COLSPAN=2><!--italics here-->italics</TD> <TD COLSPAN=2><!--blink here-->blink</TD> <TD COLSPAN=2><!--strike here-->strike</TD> <TD COLSPAN=2><!--fixed here-->fixed</TD> <TD COLSPAN=2><!--sub here-->sub</TD> <TD COLSPAN=2><!--sup here-->sup</TD> <TD COLSPAN=2><!--about here-->about</TD> </TR><TR><TD COLSPAN=2><!--big here-->big</TD> <TD COLSPAN=2><!--small here-->small</TD> <TD><!--fontsize 1 here-->1</TD> <TD><!--fontsize 2 here-->2</TD> <TD><!--fontsize 3 here-->3</TD> <TD><!--fontsize 4 here-->4</TD> <TD><!--fontsize 5 here-->5</TD> <TD><!--fontsize 6 here-->6</TD> <TD><!--fontsize 7 here-->7</TD> <TD><BR></TD><TD COLSPAN=2><BR></TD> <TD COLSPAN=2><!--help here-->help</TD> </TR><TR><TD COLSPAN=2><!--black fontcolor-->black</TD> <TD COLSPAN=2><!--red fontcolor-->red</TD> <TD COLSPAN=2><!--green fontcolor-->green</TD> <TD COLSPAN=2><!--blue fontcolor-->blue</TD> <TD COLSPAN=2><!--cyan fontcolor-->cyan</TD> <TD COLSPAN=2><!--magenta fontcolor-->magenta</TD> <TD COLSPAN=2><!--yellow fontcolor-->yellow</TD> <TD COLSPAN=2><!--preview button-->Preview</TD> </TR></TABLE> </BODY></HTML> Putting Buttons into the Table. The coding for each of the buttons follows the same format. The HTML code creates a button displaying the name of the style (for instance, bold). Each contains an onClick event, which will call a function specifically to implement that feature. However, this coding will not be written until the next phase of developing this program. The following is the code for the Bold button: <INPUT name="bold" type="button" value=" Bold " onClick="stylemethod (`bold')"> This same coding is created for Italics, Fixed, Blink, Strike, Sub, Sup, Big, Small, 1, 2, 3, 4, 5, 6, and 7. Insert this coding into the correct cells of the table. The coding for all of these is shown in Listing 14.13.

Listing 14.13 Button Inputs Defined

<INPUT name="bold" type="button" value=" Bold " onClick="stylemethod(`bold')"> <INPUT NAME="italics" TYPE="button" VALUE="Italics" onClick="stylemethod(`italics')"> <INPUT NAME="blink" TYPE="button" VALUE=" Blink " onClick="stylemethod(`blink')"> <INPUT NAME="strike" TYPE="button" VALUE=" Strike " onClick="stylemethod(`strike')"> <INPUT NAME="fixed" TYPE="button" VALUE=" Fixed " onClick="stylemethod(`fixed')"> <INPUT NAME="sub" TYPE="button" VALUE=" Sub " onClick="stylemethod (`sub')"> <INPUT NAME="sup" TYPE="button" VALUE=" Sup " onClick="stylemethod (`sup')"> <INPUT NAME="big" TYPE="button" VALUE=" Big " onClick="stylemethod (`big')"> <INPUT NAME="small" TYPE="button" VALUE="Small" onClick="stylemethod(`small')"> <INPUT NAME="1" TYPE="button" VALUE=" 1 " onClick="stylemethod (`Size 1')"> <INPUT NAME="2" TYPE="button" VALUE=" 2 " onClick="stylemethod (`Size 2')"> <INPUT NAME="3" TYPE="button" VALUE=" 3 " onClick="stylemethod (`Size 3')"> <INPUT NAME="4" TYPE="button" VALUE=" 4 " onClick="stylemethod (`Size 4')"> <INPUT NAME="5" TYPE="button" VALUE=" 5 " onClick="stylemethod (`Size 5')"> <INPUT NAME="6" TYPE="button" VALUE=" 6 " onClick="stylemethod (`Size 6')"> <INPUT NAME="7" TYPE="button" VALUE=" 7 " onClick="stylemethod (`Size 7')"> About, Help, and Preview will have their own specialized functions so they do not call the same stylemethod. The code for these buttons is: <INPUT NAME="about" TYPE="button" VALUE=" About " onClick="aboutalert()">< <INPUT NAME="help" TYPE="button" VALUE=" Help " onClick="helppage ()"> <INPUT NAME="preview" TYPE="button" VALUE="Preview" onClick="apreview(this.form)">

TIP: When you create a button, JScript makes the button just large enough to hold the

text stored in the VALUE property. You can widen a button by adding extra spaces to the text of the VALUE property. With a little experimenting, you can make most buttons appear to be the same width. However, browsers on other platforms and with other preferences may display different widths.

Hyperlinks as Controls. The third row of the control panel has seven hyperlinks that are used as controls. These are used instead of buttons to enable the user actually to see the different colors. This is essentially a simple color selector.

NOTE: A color selector can be done in a variety of ways. You can have a SELECT list showing the string literals for all 150 colors. You can create a text box for users to input hexadecimal values, or you can create a Select drop-down list that has the names of the colors. An exciting way would be to create a client-side imagemap of a color bar. The user can select a color and execute the appropriate JScript code by clicking anywhere on the color bar.

Originally, the coding for these hyperlinks used the OnClick event. The problem with that approach is that it is necessary to specify an HREF for either an anchor or an URL. If you want to implement only a JScript function without jumping to an anchor or loading an URL, then set the HREF to a nonexistent anchor. This works; however, a future version of JScript might produce an error message. The following is an example of the code originally used: <A HREF=#bold onClick="stylemethod(`red')"> <FONT color="red">Red </FONT></A> It turns out that this is a perfect case for using the new javascript: protocol. Instead of specifying an anchor, an URL, or even a mailto:, you can specify JScript code. In our case, we want to specify executing a function for the color represented by the hyperlink. So, now, the code looks like this: <A HREF="javascript: stylecolor(`red')"> <FONT color="red">Red </ FONT></A>

TIP: Easter Eggs is a term in video games for undocumented, hidden features. By using fontcolor methods, you can make a hyperlink an invisible Easter Egg. Just make the fontcolor the same as the normal text color. The only clue would be in the status bar. TIP: The javascript: protocol allows you to make hyperlinks behave like buttons.

So, if you don't like being limited to the predefined buttons, use a hyperlink, the javascript: protocol, and your own image as an icon.

Create this same coding for black, green, blue, yellow, cyan, and magenta. Obviously, if you don't like these colors, just pick another set. Insert this code into the correct cells of the table. The complete code for the tables with all of the hyperlinks and buttons is shown in Listing 14.14. This code will be found on the CD-ROM in the file messcnt2.htm. Once again, you should rename this file to messcont. htm so that it will work correctly with the message area frameset.

Listing 14.14 messcnt2.htm--Tabled Layout of Buttons


<HTML><HEAD><TITLE>Message Editor by Ray Daly</TITLE> </HEAD><BODY bgcolor ="lightgrey"> <TABLE WIDTH="100%" HEIGHT="100%" BORDER="0"> <FORM><TR><TD COLSPAN=2> <INPUT NAME="bold" TYPE="button" VALUE=" Bold " onClick="stylemethod(`bold')"></TD> <TD COLSPAN=2> <INPUT NAME="italics" TYPE="button" VALUE="Italics" onClick="stylemethod(`italics')"></TD> <TD COLSPAN=2> <INPUT NAME="blink" TYPE="button" VALUE=" Blink " onClick="stylemethod(`blink')"></TD> <TD COLSPAN=2> <INPUT NAME="strike" TYPE="button" VALUE=" Strike " onClick="stylemethod(`strike')"></TD> <TD COLSPAN=2> <INPUT NAME="fixed" TYPE="button" VALUE=" Fixed " onClick="stylemethod(`fixed')"></TD> <TD COLSPAN=2> <INPUT NAME="sub" TYPE="button" VALUE=" Sub " onClick="stylemethod(`sub')"></TD> <TD COLSPAN=2> <INPUT NAME="sup" TYPE="button" VALUE=" Sup " onClick="stylemethod(`sup')"></TD> <TD COLSPAN=2> <INPUT NAME="about" TYPE="button" VALUE=" About " onClick="aboutalert()"></TD> </TR><TR><TD COLSPAN=2> <INPUT NAME="big" TYPE="button" VALUE=" Big " onClick="stylemethod(`big')"></TD> <TD COLSPAN=2> <INPUT NAME="small" TYPE="button" VALUE="Small" onClick="stylemethod(`small')"></TD>

<TD><INPUT NAME="1" TYPE="button" VALUE=" 1 " onClick="stylemethod(`Size 1')"></TD> <TD><INPUT NAME="2" TYPE="button" VALUE=" 2 " onClick="stylemethod(`Size 2')"></TD> <TD><INPUT NAME="3" TYPE="button" VALUE=" 3 " onClick="stylemethod(`Size 3')"></TD> <TD><INPUT NAME="4" TYPE="button" VALUE=" 4 " onClick="stylemethod(`Size 4')"></TD> <TD><INPUT NAME="5" TYPE="button" VALUE=" 5 " onClick="stylemethod(`Size 5')"></TD> <TD><INPUT NAME="6" TYPE="button" VALUE=" 6 " onClick="stylemethod(`Size 6')"></TD> <TD><INPUT NAME="7" TYPE="button" VALUE=" 7 " onClick="stylemethod(`Size 7')"></TD> <TD><BR></TD> <TD COLSPAN=2><BR></TD> <TD COLSPAN=2> <INPUT NAME="help" TYPE="button" VALUE=" Help " onClick="helppage()"></TD> </TR><TR><TD COLSPAN=2 ALIGN="center"> <A HREF="javascript: stylecolor(`black')"> <FONT COLOR="black"><B>Black</B></FONT></A></TD> <TD COLSPAN=2 ALIGN="center"> <A HREF="javascript: stylecolor(`red')"> <FONT COLOR="red"><B>Red</FONT></B></A></TD> <TD COLSPAN=2 ALIGN="center"> <A HREF="javascript: stylecolor(`green')"> <FONT COLOR="green"><B>Green</B></FONT></A></TD> <TD COLSPAN=2 ALIGN="center"> <A HREF="javascript: stylecolor(`blue')"> <FONT COLOR="blue"><B>Blue</B></FONT></A></TD> <TD COLSPAN=2 ALIGN="center"> <A HREF="javascript: stylecolor(`cyan')"> <FONT COLOR="cyan">Cyan</FONT></B></A></TD> <TD COLSPAN=2 ALIGN="center"> <A HREF="javascript: stylecolor(`magenta')"> <FONT COLOR="magenta"><B>Magenta</B></FONT></A></TD> <TD COLSPAN=2 ALIGN="center"> <A HREF="javascript: stylecolor(`yellow')"> <FONT COLOR="yellow"><B>Yellow</B></FONT></A></TD> <TD COLSPAN=2> <INPUT NAME="preview" TYPE="button" VALUE="Preview" onClick="apreview(this.form)">></TD> </TR></FORM></TABLE> </BODY></HTML>

Double-Check the Layout. You now have enough code to check your layout. Start your browser and load the code you have so far. You should see a layout just like that shown in Figure 14.10. Figure 14.10 The layout of the message editor is only a facade at this point, but it is as well to get the layout done and then put code behind it. Normally, at this point in your program development, you would spend some time polishing the layout. You might rearrange the controls, change a description, or decide on a different color background. You may or may not want to do this now, depending on how you like the choices made so far. If you like what you see, let's proceed and make this thing do some work.

Program Structure or Coding the Events


Although the message editor has 26 different controls on the control panel, most perform nearly identical functions. Most controls prompt for a text string, apply a font method to the string, and then append it to the text in the textarea. The Help and About buttons simply display text. And finally, we have the best feature of all: the Preview button.

Font Methods
For all of the font style buttons, there is one function. Each button calls this function and passes a single value: the name of the style. The function uses this value in the prompt box text and to decide which method to apply to the text. Although it creates a rather long function, it does keep down the number of functions. The Function stylemethod(). The first thing stylemethod() does is to display a dialog box in which the user can enter the text. This is the text that will be highlighted in the given style. You will note that the prompt message reminds the user of the style selected. This goes after </TITLE> and before </HEAD>, and is shown in Listing 14.15.

Listing 14.15 Start Adding Functions


<SCRIPT LANGUAGE = "JScript"> <!-- hide code from other browsers function stylemethod (style) { x = prompt ("Enter your text for the style:" + style, "") if ((x!=null) && (x!="")) { //<!-- many if statements will go here --> } } // no more hiding --> </SCRIPT> The next several lines of code are a series of if statements. To the text string returned from the

prompt dialog box, we must now apply the proper font method. This is the section of code for the condition in which the style was bold: if (style=="bold") { x = x.bold() } Additional if statements must be created for each of the additional 15 font methods using buttons. This code is shown in Listing 14.16. Each of the above if statements produces a string with the appropriate HTML tags surrounding the string to be highlighted. This string is now simply appended to the existing text in the textarea.

Listing 14.16 if Statements of Style Function


if (style == "bold") { x = x.bold() } if (style == "italics") { x = x.italics() } if (style == "blink") { x = x.blink() } if (style == "strike") { x = x.strike() } if (style == "fixed") { x = x.fixed() } if (style == "sub") { x = x.sub() } if (style == "sup") { x = x.sup() } if (style == "big") { x = x.big() } if (style == "small") { x = x.small() } if (style == "Size 1") { x = x.fontsize(1) }

if (style == "Size x = x.fontsize(2) } if (style == "Size x = x.fontsize(3) } if (style == "Size x = x.fontsize(4) } if (style == "Size x = x.fontsize(5) } if (style == "Size x = x.fontsize(6) } if (style == "Size x = x.fontsize(7) }

2") {

3") {

4") {

5") {

6") {

7") {

The Function stylecolor(). Though the method of applying color to strings is the same as other font methods, we are going to add a feature when using the fontcolor method. So, we need a function just for colors, which we will call stylecolor(). When you select a color control, you will change the color in the small frame in the upper-left corner. This provides the user with feedback and visually reminds the user which color he or she has selected. The code for this function is shown in Listing 14.17. Note that the final statement of this function first extracts the value field of the MESSARET textarea of the heavy form of the document window of the MESSAREA frame, and then appends the new value of the x parameter to it.

Listing 14.17 The Function stylecolor()


function stylecolor(style) { parent.messcolr.document.bgColor = style x = prompt ("Enter your text for the style: "+ style, "") if ((x!=null)&&(x!="")) { x = x.fontcolor(style) parent.messarea.document.heavy.messaret.value = parent.messarea.document.heavy.messaret.value + x + ` ` }

The About and Help Features


So far, we have treated the About and Help buttons as part of the style function. This was great for testing the application, but we now want to make these buttons work.

The About button simply tells the user such information as where the program originated, the name of the author, and the version number. The coding is straightforward: function aboutalert () { alert ("Message Editor by Ray Daly from Using JScript") } The Help function opens a new window with a help message, as seen in Figure 14.11. This comes from another file, messhelp.htm, which is given in Listing 14.18. This file is also on the CD-ROM. The code to open this window is as follows: function helppage () { helpwin=open ("messhelp.htm", "HelpWindow","toolbar=no, scrollbars=yes") } Figure 14.11 The Help screen for Message Editor is static. A more elaborate Help screen could contain the same controls as the control panel and provide help for each control.

Listing 14.18 messhelp.htm--Implementation of the Help Screen


<HTML><HEAD><TITLE>messhelp.htm by Ray Daly </TITLE></HEAD><BODY> <CENTER><H3>Help Screen for Message Editor</H3></CENTER> <P>The purpose of this Message Editor is to allow you to create a message where you can use the various styles available to you on Web pages. These include:</P> <DL><DD> <B>Bold</B> <I>Italics</I> <BLINK>Blink</BLINK> <STRIKE>Strike</ STRIKE> Fixed <SUB>Sub</SUB> <SUP>Sup</SUP> <BR> <BIG>Big</BIG> <SMALL>Small</SMALL> <FONT SIZE="1">Size 1</FONT> <FONT SIZE="2">Size 2</FONT> <FONT SIZE="3">Size 3</FONT> <FONT SIZE="4">Size 4</FONT> <FONT SIZE="5">Size 5</FONT> <FONT SIZE="6">Size 6</FONT> <FONT SIZE="7">Size 7</FONT> <BR> <FONT COLOR="black">Black</FONT> <FONT COLOR="red">Red</FONT> <FONT COLOR="green">Green</FONT> <FONT COLOR="blue">Blue</FONT> <FONT COLOR="cyan">Cyan</FONT> <FONT COLOR="magenta">Magenta</FONT> <FONT COLOR="yellow">Yellow</FONT> </DD></DL> <P>You create messages by typing text in the text box on the lower part of the screen. Besides typing normal text, you can also manually type in HTML

tags. The Message Editor makes it easier to insert style tags by providing buttons and controls on the top portion of the screen.</P> <P>Each of the style buttons or controls works in the same fashion. Click on a button and you are prompted to type in a line of text. When you are finished typing, your text is automatically inserted into the text box with the proper HTML style tags. Try it, you can always erase it.</B> <P><B>Preview</B> your message by pressing the Preview button. This will open up a new browser window where you can see exactly how your message will look with the HTML styles applied. When you are satisfied with your work, submit it to your BBS.</P> </BODY></HTML>

The Preview
You have waited to the very end of this chapter for the best feature of this program. You may be disappointed at how short this code is. The purpose of this code is to take the HTML document created in the textarea and display it on its own page. The code is shown in Listing 14.19. The final version of the code for the MESSCONT frameset will be found in the CD-ROM file messcnt3.htm. This code includes the apreview function shown below, as well as the stylecolor, stylemethod, aboutalert, and helppage functions from the previous listings. Figures 14.12 and 14.13 show the message center with text entered, as well as that same text in the Preview window.

Listing 14.19 Preview Function


function apreview (form) { msg = open ("","DisplayWindow","toolbar=yes") starttags ="<HTML><HEAD><TITLE>Preview</TITLE></HEAD><BODY><P><PRE>" endtags = "</PRE></P></BODY></HTML>" y = starttags + parent.messarea.document.heavy.messaret.value + endtags msg.document.write (y) }

CAUTION: The function for preview is called apreview, not preview. This is because the button itself is already using the name preview. Unlike some other languages, function and

object names can conflict.

Figure 14.12 The message in the text box can be typed in or entered by pressing the control buttons. You can see how your message displays in a browser in Figure 14.13. Figure 14.13 This is the Preview window, which shows how your message will appear in a browser. Once you approve, then you submit your message. The limitation built into this design is that only one style can be applied at a time. For example, the controls do not allow bold italics or green big. Of course, you can manually enter the codes in the textarea to create these physical styles. This limitation does force your users to keep their effects simple. Such simplicity can produce better design. One useful addition that you could make would be to include a control that will add paragraph tags. As it stands, the message editor allows only a single paragraph message.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Appendix C JScript Commands and Grammar


q

JScript Commands and Grammar r JScript Statements r Operator Precedence r JScript Objects r Reserved Words r Color Values

JScript Commands and Grammar


Finding information on programming in JScript can be a bit like looking for the Holy Grail. Between Microsoft's and Netscape's sites, online tutorials, and examples, information seems to be everywhere but at your fingertips. So, here is the information you're looking for in one place, including statements, operators, and color values.

JScript Statements
The statements used to control program flow in JScript are similar to Java and C. A statement can span several lines if needed, or several statements can be placed on the same line. The important key to remember is that a semicolon must be placed between multiple statements on a single line. Because JScript is not strict in its formatting, you must provide the line breaks and indentation to make sure the code is readable and easy to understand later. break. Terminates the current for or while loop and passes control to the first statement after the loop. comment. Notes from the script author that are ignored by the interpreter. Single line comments are preceded by //. Multiple line comments begin with /* and end with */. Do not use HTML comment delimiters (<!-- and -->) with JScript code. continue. Passes control to the condition in a while loop and to the update expression in a for loop. for. Creates a loop with three optional expressions enclosed in parentheses and separated by semicolons, followed by a set of statements to be executed during the loop:

for( initialExpression; condition; updateExpression) { statements... } The initial expression is used to initialize the counter variable, which can be a new variable declared with var. The condition expression is evaluated on each pass through the loop. If the condition is true, the loop statements are executed. The update expression is used to increment the counter variable. for...in. Iterates a variable over all the properties of an object: for (var vtmp in object) { statements... } For each property, it executes the statement block with vtmp set to the current property. function. Declares a JScript function with a name and parameters. To return a value, the function must include a return statement. A function definition cannot be nested within another function. function name ([parameter] [...,parameter]) { statements... } if...else. A conditional statement that executes the first set of statements if the condition is true, and the statements following the else if false. If...else statements can be nested to any level. if (condition) { statements... } [else { statements... }] return. Specifies a value to be returned by a function. return expression; var. Declares a variable and optionally initializes it to a value. The scope of a variable is the current function or--when declared outside a function--the current document. var variableName [=value] [..., variableName [=value]] while. Repeats a loop while a conditional expression is true. while (condition) {

statements... } with. Establishes a default object for a set of statements. Any property references without an object are assumed to use the default object. with (object) { statements... } This statement is especially useful when applied to the Math object for a set of calculations. For example: with (Math) { var Value1 = cos(angle); var Value2 = sin(angle); } replaces: { var Value1 = Math.cos(angle); var Value2 = Math.sin(angle); }

Operator Precedence
Precedence refers to the order in which compound operations are computed. Operators on the same level have equal precedence. Calculations are computed from left to right on all binary operations beginning with the operators at the top of the list and working down. call, member . [] -/ >> > != >>> <= >= () ! % ~ -

negation/increment ++ multiply/divide addition/ subtraction shift relational equality bitwise AND * + << < == &

bitwise XOR bitwise OR logical AND logical OR conditional assignment comma

^ | && || ?: = , op=

JScript Objects
JScript is an object-oriented language, and as such, includes a set of built-in objects to represent the HTML document, especially form elements. Built-in objects can be accessed by both the client and server. String. Contains a string of characters. Math. Provides numerical constants and mathematical functions. Date. Stores a date in the number of milliseconds since 1/1/1970, 00:00:00, and returns a date string in the format "Thu, 11 Jan 1996 06:20:00 GMT." Array. Holds an array of elements. Document. The foundation object created with an HTML <BODY> tag and used to write other information to the page. Form. An object for gathering and echoing data, created by HTML <FORM> tags. Window. The highest precedence object accessible by JScript relating to the currently open browser window. New windows and frames can also be created.

Reserved Words
The following words cannot be used as user objects or variables in coding JScript. Not all are currently in use by JScript--they are reserved for future use. abstract boolean break byte case

catch char class const continue default do double else extends false final finally float for function goto if implements import in instanceof int interface long native new null package private protected public return short static super switch synchronized this throw throws transient true try var void while

with

Color Values
Colors can be referenced in a variety of properties in two ways: by using the string literal or an RGB hexadecimal triplet formed by combining the three color values. For example, aliceblue is represented as F0F8FF. Color/String Literal Red aliceblue antiquewhite aqua aquamarine azure beige bisque black blanchedalmond blue blueviolet brown burlywood cadetblue chartreuse chocolate coral cornflowerblue cornsilk crimson cyan darkblue darkcyan darkgoldenrod F0 FA 00 7F F0 F5 FF 00 FF 00 8A A5 DE 5F 7F D2 FF 64 FF DC 00 00 00 B8 Green F8 EB FF FF FF F5 E4 00 EB 00 2B 2A B8 9E FF 69 7F 95 F8 14 FF 00 8B 86 Blue FF D7 FF D4 FF DC C4 00 CD FF E2 2A 87 A0 A0 1E 50 ED DC 3C FF 8B 8B 0B

darkgray darkgreen darkkhaki darkmagenta darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen darkslateblue darkslategray darkturquoise darkviolet deeppink deepskyblue dimgray dodgerblue firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite gold goldenrod gray green greenyellow honeydew hotpink

A9 00 BD 8B 55 FF 99 8B E9 8F 48 2F 00 94 FF 00 69 1E B2 FF 22 FF DC F8 FF DA 80 00 AD F0 FF

A9 64 B7 00 6B 8C 32 00 96 BC 3D 4F CE 00 14 BF 69 90 22 FA 8B 00 DC F8 D7 A5 80 80 FF FF 69

A9 00 6B 8B 2F 00 CC 00 7A 8F 8B 4F D1 D3 93 FF 69 FF 22 F0 22 FF DC FF 00 20 80 00 2F F0 B4

indianred indigo ivory khaki lavender lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan

CD 4B FF F0 E6 FF 7C FF AD F0 E0

5C 00 FF E6 E6 F0 FC FA D8 80 FF FA EE D3 B6 A0 B2 CE 88 C4 FF FF CD F0 00 00 CD 00 55 70 B3

5C 82 F0 8C FA F5 00 CD E6 80 FF D2 90 D3 C1 7A AA FA 99 DE E0 00 32 E6 FF 00 AA CD D3 DB 71

lightgoldenrodyellow FA lightgreen lightgray lightpink lightsalmon lightseagreen lightskyblue lightslategray lightsteelblue lightyellow lime limegreen linen magenta maroon mediumaquamarine mediumblue mediumorchid mediumpurple mediumseagreen 90 D3 FF FF 20 87 77 B0 FF 00 32 FA FF 80 66 00 BA 93 3C

mediumslateblue mediumspringgreen mediumturquoise mediumvioletred midnightblue mintcream mistyrose moccasin navajowhite navy oldlace olive olivedrab orange orangered orchid palegoldenrod palegreen paleturquoise palevioletred papayawhip peachpuff peru pink plum powderblue purple red rosybrown royalblue saddlebrown

7B 00 48 C7 19 F5 FF FF FF 00 FD 80 6B FF FF DA EE 98 AF DB FF FF CD FF DD B0 80 FF BC 41 8B

68 FA D1 15 19 FF E4 E4 DE 00 F5 80 8E A5 45 70 E8 FB EE 70 EF DA 85 C0 A0 E0 00 00 8F 69 45

EE 9A CC 85 70 FA E1 B5 AD 80 E6 00 23 00 00 D6 AA 98 EE 93 D5 B9 3F CB DD E6 80 00 8F E1 13

salmon sandybrown seagreen seashell sienna silver skyblue slateblue slategray snow springgreen steelblue tan teal thistle tomato turquoise violet wheat white whitesmoke yellow yellowgreen

FA F4 2E FF A0 C0 87 6A 70 FF 00 46 D2 00 D8 FF 40 EE F5 FF F5 FF 9A

80 A4 8B F5 52 C0 CE 5A 80 FA FF 82 B4 80 BF 63 E0 82 DE FF F5 FF CD

72 60 57 EE 2D C0 EB CD 90 FA 7F B4 8C 80 D8 47 D0 EE B3 FF F5 00 32

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Appendix A JScript and ActiveX Resources


q

JScript and ActiveX Resources r The World Wide Web s Microsoft Corporation s JavaScript Index s Voodoo JavaScript Tutorial s Danny Goodmans JavaScript Pages s Gordon McCombs JavaScript Sourcebook s The Complete Idiots Guide to JavaScript Home Site s Gamelan s Netscape s Netscape World s JavaWorld s TeamJava s Symantec s Dimension X s The Java Developer s Sun Microsystems r UseNet Newsgroups s comp.lang.javascript s comp.lang.java s comp.infosystems.www.authoring r E-Mail Mailing Lists s javascript@obscure.org s listserv@listserv.msn.com r Search Engines s AltaVista s Yahoo! s Lycos s WebCrawler r General Web Sites s The Consummate Winsock Software List s TUCOWS s Shareware.COM r Macintosh s Internet Explorer 2.1 s Symantec Caf

r r

Roaster s CodeWarrior Various ActiveX Resources A Brief Tour of the ActiveX SDK s Documentation s Tools and Utilities s Samples ActiveX Resources on the Web s Web Sites s The ActiveX Working Group s Microsofts Knowledge Base Online s Microsoft Site Builder Workshop s World Wide Web Consortium s ActiveXtra s ZD Nets ActiveXfiles s Newsgroups s Mailing Lists Microsoft Developer Network
s

JScript and ActiveX Resources


q q q q q q

World Wide Web resources UseNet newsgroups E-mail mailing lists Search engines for further exploring Resources for the Macintosh Overview of the ActiveX SDK Other sources of information on ActiveX

Because JScript is designed for content presentation on the World Wide Web, it's only appropriate that the largest collection of resources for its implementation is found on the Internet. Because of JScript's very specific platform base (currently supported only by Microsoft's Internet Explorer ), the number of "official" online resources that directly address it are few and far between. However, the "unofficial" resources (put up by experimenting souls who want to share their discoveries of this new technology) are growing at a rapid rate. In addition, because Microsoft's JScript is very closely related to Netscape's JavaScript, many of the resources for JavaScript contain valuable information about JScript as well. Also, because JScript works well as a "glue" to bind ActiveX controls, Java applets, and frames together, it's well worth the effort to keep up-to-date on the latest in these technologies.

In this appendix, you will be introduced to the growing base of information available. This list is by no means comprehensive--as new sites appear on the Web weekly--but it's a good place to start looking for information on JScript, JavaScript, ActiveX, Java, or other related technologies.

The World Wide Web


Because JScript is for the Web, it's only appropriate that the best sources of information on its use are found on the Web. As with most other Internet-based sources, the bulk of Java and JScript sites are primarily Java-oriented with JScript covered as a subsection. The following list is by no means comprehensive, and to keep up on new offerings on the Web, your best bet is to take advantage of the Other Hot Links pages that many of the sites have.

Microsoft Corporation
http://www.microsoft.com Microsoft created the JScript implementation of JavaScript, and is also the creator of the ActiveX technology. As a result, there are a wide variety of pages at the Microsoft site that will be of interest to JScript programmers, ActiveX developers, and Java enthusiasts. This site changes frequently, with more material being added all the time. It is well worth frequent visits.

JavaScript Index
http://www.c2.org/~andreww/javascript/ JavaScript Index is a solid compendium of JavaScript implementations and experimentation, including a growing list of personal home pages that show off a variety of JavaScript tricks. A subset of the site is the JavaScript Library, a small but expanding collection of source code from around the Web community.

Voodoo JavaScript Tutorial


http://rummelplatz.uni-mannheim.de/~skoch/js/script.htm Voodoo JavaScript Tutorial is an ongoing tutorial presented in easy-to-digest sections covering the basics of JavaScript. It includes examples built into the page, along with descriptive text and code examples. It's a good place to get your feet wet.

Danny Goodmans JavaScript Pages


http://www/dannyg.com/javascript/index.html

This is a collection of examples covering more advanced concepts in JavaScript, including cookies. Danny Goodman is one of the de facto experts on JavaScript on the Web, and provides some good examples to learn and adapt other applications from.

Gordon McCombs JavaScript Sourcebook


http://gmccomb.com/javascript/ Author and consultant Gordon McComb hosts this page, which is packed with information, examples, and JavaScript how-to's.

The Complete Idiots Guide to JavaScript Home Site


http://www.winternet.com/~sjwalter/javascript/ This is the online companion to the book by the same name (also published by Que). Source code for the printed examples, links to other resources and sites, and regular tutorial sections on various parts of JavaScript are offered.

Gamelan
http://www.gamelan.com/ Called "the online Java index," EarthWeb's Gamelan has an extensive collection of links to other sites, examples, tools, utilities, and other interesting resources. Although primarily targeting Java, the JavaScript section is quite sizable as well.

Netscape
http://home.netscape.com/ Netscape's home site is a good place to check periodically, especially for updates and additions to the JavaScript language specification.

Netscape World
http://www.netscapeworld.com/ This is another new online eZine, dedicated to Netscape products. If you're interested in seeing just how powerful JavaScript can be, this is an excellent example of JavaScript in action.

JavaWorld

http://www.javaworld.com/ IDG Communications (which also publishes SunWorld Online, Macworld, PC World, and Computerworld) has introduced this online version of its new magazine. While dedicated to Java programming and industry developments, it also has an ongoing column on JavaScript.

TeamJava
http://www.teamjava.com/ TeamJava is a group consisting of Web gurus, consultants, Internet programmers, Webwriters, and other such denizens of the Net. Their home page has links to other Java and JavaScript resources, as well as information on how to contact the consultants themselves.

Symantec
http://www.symantec.com/ Symantec led the pack when it came to providing a development platform for Java applet creation. With Caf, the first publicly available Java development add-on to their popular C++ package, Symantec provided the Web community with the first GUI-based development environment for applet creation.

Dimension X
http://www.dnx.com/ Dimension X is the home of Liquid Reality, a Java applet development platform that merges the capabilities of a 3-D modeling package with a Java app builder.

The Java Developer


http://www.digitalfocus.com/faq/ Sponsored by Digital Focus, the Java Developer serves as the home site for The Java Developer FAQ and one of the more interesting implementations of frames to present search-and-question submission buttons as you browse the site.

Sun Microsystems
http://www.javasoft.com/

The place where it all started, Sun hosts the Java home site. Additionally, Sun maintains several mailing and notification lists to keep developers informed of the latest events.

UseNet Newsgroups
Several UseNet newsgroups have sprung up to provide channels for developers looking for guidance with Java, JavaScript, and Web programming in general. They all have global distribution and should be available from your Internet provider.

comp.lang.javascript
As the only newsgroup specifically dedicated to JavaScript development, this one gets somewhat lively at times.

comp.lang.java
Although this collection of groups is focused on the discussion of Java programming tricks and tips, integrating JavaScript into Web content is also talked about. This group has several interesting subgroups, including .annouce, .api, and .setup.

comp.infosystems.www.authoring
The traditional collection of newsgroups for WWW-oriented discussion has been comp.infosystems. www. As the Web has expanded, so have they, covering everything from browsers to announcements of newly opened Web sites. Even though there is no group specifically for JavaScript in the comp.infosystems hierarchy, the following groups--which cover various facets of Web authoring--are of interest:
q q q q

comp.infosystems.www.authoring.cgi comp.infosystems.www.authoring.html comp.infosystems.www.authoring.images comp.infosystems.www.authoring.misc

E-Mail Mailing Lists


For those who prefer the thrill of receiving tons of e-mail, there are mailing lists dedicated to Java and JavaScript that offer similar information to that found in UseNet newsgroups. Keep in mind, however, that mailing lists are a lot like a party line and can get rather chatty (the downside being you have to wade through all the flotsam in your in box to figure out what you can use). If you plan to use mailing lists heavily, you might want to look into an e-mail program that supports threading: the linking together of messages that share the same subject. (It really helps organize the flood of information.)

NOTE: Although you post your questions and comments to the address of the list (for broadcast to the rest of the list's readers), subscribing to and unsubscribing from the list are done through a separate e-mail address, specifically the address of the list server. The following lists mention both the list address and the list server address, and sending subscribe requests to the list address (so everyone on the list knows you don't know what you're doing) is a guaranteed way to get branded a newbie. If you want more information on how to communicate with the list server (or on other lists a particular server might have), you can send a message to the list server address with "help" in the message body.

javascript@obscure.org
Sponsored by the Obscure Organization (http://www.obscure.org/) and TeleGlobal Media, Inc. (http://www.tgm.com/), the JavaScript Index is the only mailing list at the time of this writing dedicated specifically to JavaScript. The discussion gets pretty varied and ranges from introductory questions to more involved discussions on how best to handle animation, framing, reloads, and so on. To subscribe, send a message to majordomo@obscure.org with "subscribe javascript" in the message body. Alternatively, you can point your browser at http://www.obscure.org/javascript/ for further information.

listserv@listserv.msn.com
This list server sponsors a number of mailing lists devoted to Web-related topics. While there is no JScript list at the time of this writing, there are lists for ActiveX, Java, and other topics of interest to Webmasters.

Search Engines
There are several search engines available to JavaScript, including AltaVista, Yahoo!, Lycos, and WebCrawler.

AltaVista
http://www.altavista.com/ A newcomer to the search engine world, AltaVista sports over 15 million entries, making it the largest search site currently in cyberspace. This site attempts to catalog not only sites and pages but words within pages, making it very easy to generate thousands of matches for a particular search term (for example, searching on "JavaScript" will find not only sites that deal with JavaScript, but sites

that use it within their pages because that word is always part of the <SCRIPT> tag). To make the best use of this site, try to be as specific as possible, or be prepared to refine and narrow down your search parameters.

Yahoo!
http://www.yahoo.com/ Yahoo is short for "You Always Have Other Options," and although this is most definitely true on the Net, you'd be hard pressed to find others as broad.

Lycos
http://www.lycos.com/ One of the granddaddies of the search world, Lycos has a massive database, and a large collection of references to Java, JavaScript, and Web design in general.

WebCrawler
http://www.webcrawler.com/ Supported by America Online, WebCrawler is a broad-spectrum search system that's fast (one of the fastest reply systems on the Net).

General Web Sites


There are several sites on the Web that serve as a central clearinghouse for Internet- related applications (many of which are being developed as low-cost shareware by private individuals). Although these sites address a broader base than Java or JavaScript, they are expanding their coverage to include Java editors, extended HTML tools, and the like.

The Consummate Winsock Software List


http://cws.wilmington.net/ The Consummate Winsock Software (CWS) List is just as the name implies: a very complete collection of the best, the latest, the greatest, and the not so great. Combining a five-star rating system and a thorough collection of product reviews (including both pro and con analysis of all products), CWS is an excellent place to keep up with what's new and different.

TUCOWS

http://www.tucows.com/ The Ultimate Collection of Winsock Software (hence the acronym), TUCOWS rivals CWS for its completeness and variety in content. There is naturally some duplication between the two sites (the most popular pieces of software on the Net are found at both), but one complements the other quite nicely. (For the broadest picture of what's available, it's worth stopping by both.) Similar to CWS, TUCOWS has a "cow" rating system, which highlights hot, "get it" titles.

Shareware.COM
http://www.shareware.com/ What started as the Virtual Shareware Library (VSL), this site has been taken over by c|net central, an online/on-TV source for the latest-breaking information on Internet technology. Although it doesn't attempt to rate software, it does provide a "top downloads" list to indicate what Netizens have deemed the hot products of the moment. Unlike CWS and TUCOWS, which link one product to one download link, shareware.com's download section presents a list of sites (rated by reliability) around the world from which you can retrieve a particular file.

Macintosh
Because the vast majority of users on the Internet are connecting with Windows or UNIX machines, the bulk of the resources (especially the plug-ins) detailed previously are for UNIX or Windows platforms, leaving Macintosh users out in the cold (a point that is periodically brought up in the online discussions about whose system is better). Such companies as Symantec are scheduled to provide Mac versions of their Java frameworks, but they aren't available yet. There are, however, several resources for Mac users that are well worth checking out.

Internet Explorer 2.1


Although the Macintosh version of Internet Explorer does not provide the same set of features as Internet Explorer 3.0, it does support JavaScript and Java. By the time you read this, a full release for the Macintosh may well be available. If you want to take advantage of IE, you need to stop by Microsoft's home site (http://www.microsoft.com/) and download a copy of the 2.1 release of Internet Explorer.

Symantec Caf
http://www.symantec.com/

Symantec's Caf development platform is now available for Windows 95, Windows NT, and the Macintosh. Check out the Java Center for additional Java-related product information.

Roaster
http://www.natural.com/ For Java applet developers, Roaster was the first Mac development environment that provides a GUI platform for the creation of Java applets.

CodeWarrior
http://www.metrowerks.com/ CodeWarrior is the most popular C++ development platform for Macintosh and PowerPC developers today. Metrowerks has extended their development environment to also support Java.

Various ActiveX Resources


In this book, you learn how to use ActiveX controls in your Web pages. You learn how to insert them using the OBJECT tag and how to set their properties using the PARAM tag. You also learn how to associate scripts with controls using the FOR and EVENT attributes of the SCRIPT tag. These are all authoring details. This appendix shows you how to find more technical information about ActiveX technology. It introduces you to the ActiveX SDK, for example, and points you to some of the best resources on the Internet for ActiveX information and resources. Finally, it introduces you to the Microsoft Developer Network, which no self-respecting ActiveX programmer should be without.

A Brief Tour of the ActiveX SDK


The ActiveX SDK contains the tools you need to build Internet applications. It contains the files you need to build ActiveX controls, for example, or to integrate Internet technology into your existing applications. For that matter, you can use the ActiveX SDK to build your own Internet tools, such as browsers and news readers. Here's a quick run- down of what you'll find in the SDK (the sections that follow describe it in more detail):
q

The SDK contains specifications that describe various aspects of ActiveX such as ActiveX controls. The SDK contains utilities you use to certify your ActiveX controls so that people who download them can know that they haven't been tampered with. The SDK is loaded with examples that you can use as a starting point or to learn more about building Internet applications with the SDK.

The SDK contains all of the interface files (LIB, H, and so on) and redistributable files that you need to build Internet applications with Visual C++ and the WIN32 SDK.

You can get your own copy of the ActiveX SDK from Microsoft's Web site. In your favorite Web browser, open http://www.microsoft.com/msdownload/activex.htm, and follow the instructions you see on the Web page.

TIP: Microsoft updates the ActiveX SDK quite frequently. Thus, you should check Microsoft's Web site often for new versions of the SDK.

Documentation
The ActiveX SDK contains a handful of documentation that you must read if you're a serious ActiveX developer. Here's a sample of what you'll find in the \Specs folder under the folder in which you installed the SDK:
q q

q q q q q q

q q

Vbstutor.htm is an HTML file that contains a VBScript tutorial. Asynchronous Storage.doc is a specification that describes asynchronous compound documents. Asyncmon.doc is a specification that describes asynchronous monikers. Hlink.doc is a specification that describes the ActiveX hyperlink architecture. Hlsimple.doc is a specification that describes the simple hyperlink navigation API. Oc96.doc is the OLE Controls 96 specification. Ocguide.doc is the OLE Control and Control Container Guidelines specification. OLE Controls-COM Objects for the Internet.doc is the specification that describes the requirements for Internet aware controls. OLE Document Objects Specification.doc is the DocObjects specification. Urlmon.doc is the URL Moniker specification.

The ActiveX SDK also installs a handful of help files that you can use for quick reference. You'll find an overview of the ActiveX SDK in your Start menu: Choose Programs, ActiveX SDK, ActiveX SDK Overview to open an overview of the SDK in your Web browser. Choose Programs, ActiveX SDK, ActiveX SDK Help InfoViewer from the Start menu to open the ActiveX documentation in Microsoft's InfoViewer.

Tools and Utilities


The ActiveX SDK has a lot of tools that make your job a lot easier. For example, it contains a set of tools you can use to build CAB files. It contains tools you can use to certify your new ActiveX controls. You'll find all of these tools in the \Bin folder under the folder in which you installed the SDK. Microsoft hasn't done a very good job of pointing all these tools out to you, so I've endeavored

to do so in the following list:


q q q

q q q

q q q q q

Cabdevkt.exe is a self-extracting file that installs the CAB development kit. DumpCert.exe is a tool that dumps the certification information for a signed program. WINTDisk.exe, APRXDist.exe, CCDist.exe, CCDist35.exe, WIN351.exe, AXDist.exe are compressed files that contain redistributable files. \DOC\Redist \Redist.txt contains licensing information about these files. Oleview.exe is a utility you can use to browse the OLE controls installed on a computer. Ods_tool.exe is a tool that creates STM files for use with the OBJECT tag. Makecert.exe is the tool you use to make the public and private keys for use in a digital signature. Cert2spc.exe is the tool you use to package a certificate as a signed-data object. Signcode.exe is the tool you use to actually sign the image file. Pesigmgr.exe is the tool you use to verify an image file's signature after you sign it. Chktrust.exe is the tool you use to verify that an image file hasn't been tampered with. Lpk_tool.exe (License Packaging Tool) is a tool that creates license packages so that you can redistribute licensed controls with your Web page. Webpost.exe is a tool you can use to automatically post your HTML files to a Web server-particularly if you're using an Internet service provider.

Samples
The examples included in the ActiveX SDK are the best place to look for carnal knowledge of the SDK. They demystify the SDK. These examples show you how to use the SDK to create Internet applications, ActiveX controls, or a host for ActiveX Scripting. Following are the examples you'll find in the \Samples directory under the directory in which you installed the SDK:
q q q q q q q q q q

AXScript is an example of ActiveX scripting host. BaseCtrl is a sample of ActiveX Control. Framer is a sample of DocObject in-place activation. MSConf is an example of using ActiveX Conferencing. Progress is a sample of using an URL Moniker. Range is a demonstration of an HTTP GET request. UrlPad is a sample that edits HTML on the server. VBScript contains sample of VBScript/JScript Web pages. WebPost is a demonstration of the WebPost API. WinINet is a demonstration of the WinINet APIs.

ActiveX Resources on the Web


It's tough to keep current with Microsoft. By necessity, they keep a pace that makes most people's heads spin. The best way to stay up-to-date is to visit the resources available on the Internet for ActiveX folks like you. You'll find a plethora of Web sites, newsgroups, and mailing lists that'll help you stay at the

head of the pack.

Web Sites
The Web is your number one resource for ActiveX documentation. You'll find Web pages about ActiveX controls and other ActiveX technologies. You'll also find information about Microsoft's technological strategy. Take a look at the sites in the following sections.

The ActiveX Working Group


http://www.activex.org Microsoft has very recently turned over ActiveX to a steering committee that will oversee the development of the ActiveX standards. Microsoft's hope in all this is that ActiveX will gain broader acceptance if the technology remains open and customer-driven. They also hope to evolve ActiveX across multiple platforms such as UNIX. The ActiveX Working Group's Web site is somewhat sparse as of this writing, but in the near future, this will be the place to check for information about all ActiveX standards. The biggest advantage for Microsoft is that they can detach themselves slightly from a technology that means everything to their success. Thus, the mudslingers and Microsoft naysayers won't be as likely to pooh-pooh ActiveX just because it's a Microsoft technology.

Microsofts Knowledge Base Online


http://www.microsoft.com/kb Microsoft's Knowledge Base contains thousands of articles, each of which provides information about a specific problem. Each article describes the problem's symptoms, causes, resolution, and, sometimes, status. For example, you might learn that the reason your desktop redraws so painfully slow is because the video driver has a bug that you can repair by changing a setting in the Registry. Open http://www.microsoft.com/kb in your Web browser and you'll see Microsoft's Knowledge Base. The types of articles that the Knowledge Base contains are quite impressive. Following are the categories that you find as of this writing:
q q q q q q q

Application Notes Available Confirmed Bugs Display (Video, Monitor, Resolution) Issues Documentation Errors Environment and Configuration Issues Error Message Follow-Up Information Files Available for Download

q q q q q q q q q q q q q q q

Fixed Bugs General Programming Issues Hardware Interaction Between Microsoft Products Interactions with Third-Party Products Multimedia, Including Programming Issues Networking, Including Programming Issues OLE, Including Programming Issues Product Features or Functionality Printing, Including Programming Issues Problems Not Classified as Bugs (Features?) Sample Code Sample Macros Setup and Installation Issues Step-by-Step Procedures for Tasks Sound (Audio) Issues Tools, Utilities, Wizards, and so on Troubleshooting Information User Interface, Including Programming Issues

Microsoft Site Builder Workshop


http://www.microsoft.com/workshop The Site Builder Workshop is a huge Web site that documents every facet of Microsoft's Internet technology, including ActiveX. You'll find the following six different types of information for Internet professionals:
q

Authoring/Editing is for professionals who create Web pages. You'll find information to help you build Web pages such as an HTML reference. Design/Creative is for the graphically oriented professionals. You'll find information about graphics and Web page layout. Programming is for those responsible for building Internet applications or ActiveX controls. It contains update specifications, samples, and more. Site Administration is all about administering large Web sites. You'll find information such as using Visual Source Safe to manage HTML files. Planning/Production contains information about Internet business. You'll learn about production issues, marketing, and planning. Web Gallery is a huge resource of multimedia that you can use in your Web pages. You can lift graphics, sounds, and controls from this site.

World Wide Web Consortium

http://www.w3.org The World Wide Web Consortium (W3C) is the organization that defines many of the standards that drive the Web. For example, W3C is responsible for defining HTML 3.2, which includes innovations such as style sheets and the OBJECT tag. The working documents on these two Web pages are of particular interest. They are as follows: http://www.w3.org/pub/WWW/TR/WD-object.html is a working document for the multimedia object specification--the OBJECT tag. http://www.w3.org/pub/WWW/TR/WD-script.html is a working document for the specification that describes HTML extensions to support executable scripts--JavaScript and VBScript.

ActiveXtra
http://www.activextra.com If you're feeling totally lost and overwhelmed by all this ActiveX stuff, check out ActiveXtra from TechWeb. This site provides the latest news about ActiveX, technical documentation, and tools. It's definitely the place to get started.

ZD Nets ActiveXfiles
http://www.zdnet.com/activexfiles Besides being a great pun on The X-Files, this site provides the latest tools you can use with ActiveX. You'll find controls and other utilities. You'll also find plenty of news and information about ActiveX.

Newsgroups
UseNet newsgroups are a good place to get your questions answered by other professionals like you. You'll find a newsgroup for just about every topic imaginable. Following is a list of the most useful newsgroups for ActiveX programmers (their names are self-explanatory): alt.winsock alt.winsock.programming comp.infosystems.www.authoring.cgi comp. infosystems.www.authoring.html comp.infosystems.www.authoring.images comp. infosystems.www.authoring.misc comp.infosystems.www.browsers.ms-windows comp.infosystems.www.servers.ms-windows comp.lang.c comp.lang.c++ comp.os. ms-windows.apps.winsock.mail comp.os.ms-windows.apps.winsock.misc comp.os. ms-windows.apps.winsock.news comp.os.ms-windows.networking.tcp-ip comp.os. ms-windows.networking.win95 comp.os.ms-windows.programmer.controls comp.

os.ms-windows.programmer.misc comp.os.ms-windows.programmer.networks comp.os.ms-windows.programmer.ole comp.os.ms-windows.programmer.tools. mfc comp.os.ms-windows.programmer.tools.misc comp.os.ms-windows. programmer.tools.winsock comp.os.ms-windows.programmer.win32 comp. security.announce comp.security.misc microsoft.public.activex.controlpad microsoft.public.inetserver.iis microsoft.public.inetserver.misc microsoft.public. internetexplorer microsoft.public.vb.controls.internet microsoft.public.vc. activextemplatelib sci.crypt

Getting Your Questions Answered You find millions of postings on UseNet every day. You have to believe that at least one person in the world has already answered the question that is currently on your mind, right? The problem is that you can't wade through all of the postings to find the answer. It's not practical. DejaNews, at http://www.deja.com, is a perfect resource for locating those answers. Open it in your Web browser, type a few keywords that are related to your questions, and click Find. DejaNews presents you with a list of all the postings it finds that contain those keywords. You may notice that many of the message headers begin with RE:. These are replies to original questions and are great places to start when you're looking for answers to your questions. You can also use DejaNews to locate newsgroups that discuss a particular topic. The second text box on this Web page lets you specify a couple of keywords to which DejaNews responds with a list of newsgroups in which those keywords are frequently used. You can use DejaNews to locate the newsgroups that discuss the ActiveX Menu control, for example.

Mailing Lists
Microsoft sponsors a number of mailing lists to facilitate communication about its technology. It has a number of notable ActiveX-related mailing lists, too. The following sections describe each list and show you how to subscribe to it. ActiveXControls. The ActiveXControls mailing list includes discussion about the development of ActiveX controls. To subscribe, send an e-mail message to listserv@listserv.msn.com with subscribe ActiveXControls Your Name in the body of the message. ActiveXScript. The ActiveXScript mailing list includes discussion about the development of ActiveX scripting engines and usage of the ActiveX scripting languages. To subscribe, send an e-

mail message to listserv@listserv.msn.com with subscribe ActiveXScript Your Name in the body of the message. Authenticode. The Authenticode mailing list includes discussion about the Windows Trust Verification Services, which is a set of APIs that verifies the digital certificate of a software component. To subscribe, send an e-mail message to listserv@listserv.msn.com with subscribe Authenticode Your Name in the body of the message. CodeDownload. The CodeDownload mailing list includes discussion about component download. To subscribe, send an e-mail message to listserv@listserv.msn.com with subscribe CodeDownload Your Name in the body of the message. Denali. The Denali mailing list includes discussion about the ActiveX Server Framework, which is the component for developing Web server applications. To subscribe, send an e-mail message to listserv@listserv.msn.com with subscribe Denali Your Name in the body of the message. DocObjects. The DocObjects mailing list includes discussion about the development of document objects. To subscribe, send an e-mail message to listserv@listserv.msn.com with subscribe DocObjects Your Name in the body of the message. IE-HTML. The IE-HTML mailing list includes discussion about writing HTML for Internet Explorer and includes discussion of the OBJECT and SCRIPT tags. To subscribe, send an e-mail message to listserv@listserv.msn.com with subscribe IE-HTML Your Name in the body of the message. OLEHyperlinking. The OLEHyperlinking mailing list includes discussion about the ActiveX hyperlinking services and interfaces. To subscribe, send an e-mail message to listserv@listserv.msn. com with subscribe OLEHyperlinking Your Name in the body of the message. URLMonikers. The URLMonikers mailing list includes discussion about URL monikers and asynchronous monikers. To subscribe, send an e-mail message to listserv@listserv.msn.com with subscribe URLMonikers Your Name in the body of the message. VBScript. The VBScript mailing list includes discussion about VBScript. To subscribe, send an email message to listserv@listserv.msn.com with subscribe VBScript Your Name in the body of the message. WebPost. The WebPost mailing list includes discussion about the WebPost API. To subscribe, send an e-mail message to listserv@listserv.msn.com with subscribe WebPost Your Name in the body of the message.

Microsoft Developer Network

Microsoft Developer Network (MSDN) is a very popular resource for Windows developers. You can always point out a serious Windows developer because he has the Development Library stuffed into his CD-ROM. Like TechNet, you subscribe to MSDN to receive quarterly updates. Unlike TechNet, MSDN has different subscriptions depending upon how many goodies you need (and can afford): Library The Library subscription gets you the Development Library, which is a CD-ROM that contains over 1.5G of documentation, articles, samples, and the Developer Knowledge Database. You also get the Developer Network News and a discount on Microsoft Press books. Cost: $199 per year.

Professional The Professional subscription gets you everything in the Library subscription as well as the Development Platform, which is a set of CD-ROMs that contain all of the software development and device driver kits; Windows and Windows NT Workstation operating systems; and premium shipments of important system releases. The professional subscription is $499 per year. Enterprise The Enterprise subscription gets you everything in the Professional subscription, plus the BackOffice Test Platform, which contains the latest server components of Microsoft BackOffice. The enterprise subscription is $1,499 per year. The Universal subscription is the ultimate Subscription level. It contains everything in the Enterprise level. It also includes all of the Microsoft Visual Tools (Visual Basic and Visual C++, for example), Microsoft Office products, and upcoming development tools. The Universal subscription costs a whopping $2,499 per year. Ouch.

Universal

You can subscribe to the Microsoft Developer Network by calling (800) 759-5474. Note that if you already subscribe to one of the subscription levels, Microsoft offers a reasonable upgrade fee to one of the higher levels. DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Appendix B JScript Glossary


q

JScript Glossary r Terms r Objects r Properties r Methods r Event Handlers

JScript Glossary
Terms
While not necessarily JScript objects or keywords, the following items can help in your understanding of JScript and how it works. These are the general terms that are used in most discussions about JScript and its implementation. Cookie. A special object containing state/status information about the client that can be accessed by the server. Included in that state object is a description of the range of URLs for which that state is valid. Future HTTP requests from the client falling within a range of URLs described within the state object will include transmission of the current value of the state object from the client back to the server. This simple form of data storage allows the server to provide "personalized" service to the client. Online merchants can store information about items currently in an "electronic shopping basket," services can post registration information and automate functions such as typing a user ID, and user preferences can be saved on the client and retrieved by the server when the site is contacted. For limited-use information such as shopping services, it is also possible to set a time limit on the life of the cookie information. CGI scripts are typically used to set and retrieve cookie values. To generate the cookie requires sending an HTTP header in the following format: Set-Cookie: NAME=Value; [EXPIRES=date;] [PATH=pathname;] [DOMAIN=domainname;] [SECURE] When a request for cookie information is made, the list of cookie information is searched for all URLs which match the current URL. Any matches are returned in this format:

cookie: NAME1=string1; NAME2=string2; ... Cookie was an arbitrarily assigned name. For more information about the cookie and its function, see http://home.netscape.com/newsref/std/cookie_spec.html. Event Handler. Attributes of HTML tags embedded in documents. The attribute assigns a JScript command or function to execute when the event happens. Function. A user-defined or built-in set of statements that perform a task. It can also return a value when used with the return statement. Hierarchy. Browser objects exist in a set relation to each other that reflects the structure of an HTML page. This is referred to as instance hierarchy because it only works with specific instances of objects, rather than general classes. The window object is the parent of all other browser objects. Underneath, window, location, history, and document all share precedence. Document includes forms, links, and anchors. Each object is a descendant of the higher object. A form called orderForm is an object, but is also a property of document. As such, it is referred to as document.orderForm. Java. An object-oriented, platform-independent programming language developed by Sun Microsystems and used to add additional functionality to Web pages. Programming in Java requires a Java compiler, such as the Java Development Kit, and the Java core classes. JavaScript. A scripting language developed by Netscape for HTML documents. Scripts are performed after specific user-triggered events. Creating JavaScript Web documents requires a text editor and compatible browser. JScript is Microsoft's implementation of JavaScript for their Internet Explorer browser. Literal. An absolute value not assigned to a variable. Examples include 1, 3.1415927, "Bob", true. Method. A function assigned to an object. For example, bigString.toUpperCase() returns an uppercase version of the string contained in bigString. Object. A construct with properties that are JScript variables or other objects. Functions associated with an object are known as the object's methods. You access the properties of an object with a simple notation: objectName.propertyName Both object and property names are case-sensitive. Operator. Performs a function on one or more operands or variables. Operators are divided into two classes: binary and unary. Binary operators need two operands, and unary operands can operate on a single operand. For example, addition is a binary operand:

sum = 1 + 1 Unary operands are often used to update counters. The following example increases the variable by 1: counter++ See Appendix C, "JScript Commands and Grammar," for a list of operators and their precedence. Property. Used to describe an object. A property is defined by assigning it a value. There are several properties in JScript that contain constants: values that never change. Script. One or more JScript commands enclosed with a <script> tag.

Objects
JScript is an object-oriented language, so at its heart are a predefined set of objects that relate to the various components of an HTML page and their relation to each other. To view or manipulate the state of an object requires the use of properties and methods, which are also covered in this appendix. If an object is also used as a property of another object, that relationship is listed following the definition. Related properties, methods, and event handlers for each object are listed following the definition. anchors. A piece of text that can be the target of a hypertext link. This is a read-only object that is set in HTML with <A> tags. To determine how many anchors are included in a document, use the length property. document.anchors.length Property of document. See link OBJECT; see anchor METHOD. button. An object that is a form element and must be defined within a <form> tag and can be used to perform an action. Property of form. See OBJECTS reset and submit; see PROPERTIES name and value; see click METHOD; see onClick EVENT HANDLER. checkbox. A form element that the user sets to on or off by clicking and that must be defined in a <form> tag. Using the checkbox object, you can see whether the box is checked and review the name and value. Property of form. See radio OBJECT; see PROPERTIES checked, defaultChecked, name, value; see click METHOD; see onClick EVENT HANDLER. Date. Replaces a normal date type. Although it does not have any properties, it is equipped with a wide range of methods. In its current release, Date does not work with dates prior to 1/1/70. Methods for getting and setting time and date information are divided into four classes: set, get,

to, and parse/UTC. Except for the date, all numerical representations of date components begin with zero. This should not present a problem except with months, which are represented by zero (January) through 11 (December). The standard date syntax is "Thu, 11 Jan 1996 06:20:00 GMT". U.S. time zone abbreviations are also understood; but for universal use, specify the time zone offset. For example, "Thu, 11 Jan 1996 06:20:00 GMT+0530" is a place five hours and 30 minutes west of the Greenwich meridian. See METHODS getDate, getDay, getHours, getMinutes, getMonth, getSeconds, getTime, getTimezoneOffset, getYear, parse, setDate, setHours, setMinutes, setMonth, setSeconds, setTime, setYear, toGMTString, toLocaleString, toString. document. An object created by the browser when a page is loaded, containing information on the current document, such as title, background color, and forms. These properties are defined within <body> tags. It also provides methods for displaying HTML text to the user. You can reference the anchors, forms, and links of a document by using the anchors, forms, and links arrays of the document object. These arrays contain an entry for each anchor, form, or link in a document. Property of window. See frame OBJECT; see PROPERTIES alinkColor, anchors, bgColor, cookie, fgColor, forms, lastModified, linkColor, links, location, referrer, title, vlinkColor; see METHODS clear, close, open, write, writeln; see onLoad and onUnload event handlers. elements. An array of form elements in source order, including buttons, check boxes, radio buttons, text, and text area objects. The elements can be referred to by their index: formName.elements[index] Elements can also be referenced by the element name. For example, a password element called newPassword is the second form element on an HTML page. Its value is accessed in three ways: formName.elements[1].value formName.elements["newPassword"].value formName.newPassword.value Values cannot be set or changed using the read-only elements array. Property of form. See length PROPERTY. form. A property of the document object. Each form in a document is a separate and distinct object that can be referenced using the form object. The form object is an array created as forms are defined through HTML tags. If the first form in a document is named orderForm, then it could be

referenced as document.orderForm or document.forms[0]. Property of document. See hidden OBJECT; see PROPERTIES action, elements, encoding, forms, method, name, target; see submit METHOD; see onSubmit EVENT HANDLER. frame. A window that contains HTML sub-documents that are independently scrollable. Frames can point to different URLs and be targeted by other frames--all in the same window. Each frame is a window object defined using the <frameset> tag to define the layout that makes up the page. The page is defined from a parent HTML document. All sub-documents are children of the parent. If a frame contains definitions for SRC and NAME attributes, then the frame can be identified from a sibling by using the parent object as parent.frameName or parent.frames[index]. Property of window. See document and window OBJECTS; see PROPERTIES defaultStatus, frames, parent, self, status, top, window; see METHODS setTimeout and clearTimeout. hidden. A text object suppressed from appearing on an HTML form. Hidden objects can be used in addition to cookies to pass name/value pairs for client/server communication. Property of form. See PROPERTIES cookie, defaultValue, name, value. history. This object contains URL link information for previously visited pages. Property of document. See location OBJECT; see length PROPERTY; see METHODS back, forward, go. link. A location object. In addition to providing information about existing hypertext links, the link object can also be used to define new links. Property of document. See anchor OBJECT; see PROPERTIES hash, host, hostname, href, length, pathname, port, protocol, search, target; see link METHOD; see onClick and onMouseOver EVENT HANDLERS. location. Contains complete URL information for the current document, while each property of location contains a different portion of the URL. Property of document. See history OBJECT; see PROPERTIES hash, host, hostname, href, location, pathname, port, protocol, search, target. Math. Includes properties for mathematical constants and methods for functions. For example, to access the value of pi in an equation, use: Math.PI Standard trigonometric, logarithmic, and exponential functions are also included. All arguments in trigonometric functions use radians. See PROPERTIES E, LN10, LN2, PI, SQRT1_2, SQRT2; see METHODS abs, acos, asin, atan, ceil, cos, exp, floor, log, max, min, pow, random, round, sin, sqrt, tan. navigator. Contains information on the current version of the browser used by the client. See OBJECTS link and anchors; see PROPERTIES appName, appCodeName, appVersion,

userAgent. password. Created by HTML password text fields, and are masked when entered by the user. It must be defined with an HTML <form> tag. Property of form. See text OBJECT; see PROPERTIES defaultValue, name, value; see METHODS focus, blur, select. radio. Objects created within HTML <form> tags representing radio buttons. A set of radio buttons enables the user to select one item from a list. When it is created, it takes the form of document. formName.radioName[index], where the index is a number representing each button beginning with zero. Property of form. See OBJECTS checkbox, select; see PROPERTIES checked, defaultChecked, index, length, name, value; see click METHOD; see onClick EVENT HANDLER. reset. Correlates with an HTML reset button, which resets all form objects to their default values. A reset object must be created within a <form> tag. Property of form. See OBJECTS button and submit; see PROPERTIES name and value; see click METHOD; see onClick EVENT HANDLER. select. A selection list or scrolling list on an HTML form. A selection list enables the user to choose one item from a list, while a scrolling list enables the choice of one or more items from a list. Property of form. See radio OBJECT; see PROPERTIES length, name, options, selectedIndex; see METHODS blur and focus; see EVENT HANDLERS onBlur, onChange, onFocus. For the options PROPERTY of select, see defaultSelected, index, selected, text, value. string. A series of characters defined by double or single quotes. For example: myDog = "Brittany Spaniel" returns a string object called myDog with the value "Brittany Spaniel". Quotation marks are not a part of the string's value--they are used only to delimit the string. The object's value is manipulated using methods that return a variation on the string, for example myDog.toUpperCase () returns "BRITTANY SPANIEL". It also includes methods that return HTML versions of the string, such as bold and italics. See text and textarea OBJECTS; see length PROPERTY; see METHODS anchor, big, blink, bold, charAt, fixed, fontcolor, fontsize, indexOf, italics, lastIndexOf, link, small, strike, sub, substring, sup, toLowerCase, toUpperCase. submit. Causes the form to be submitted to the program specified by the action property. It is created within an HTML <form> tag. It always loads a new page, which may be the same as the current page if an action isn't specified. Property of form. See OBJECTS button and reset; see PROPERTIES name and value; see METHOD click; see EVENT HANDLER onClick.

text. A one-line input field on an HTML form that accepts characters or numbers. Text objects can be updated by assigning new contents to their value. Property of form. See OBJECTS password, string, textarea; see PROPERTIES defaultValue, name, value; see METHODS focus, blur, select; see EVENT HANDLERS onBlur, onChange, onFocus, onSelect. textarea. Similar to a text object, with the addition of multiple lines. A textarea object can also be updated by assigning new contents to its value. Property of form. See OBJECTS password, string, text; see PROPERTIES defaultValue, name, value; see METHODS focus, blur, select; see EVENT HANDLERS onBlur, onChange, onFocus, onSelect. window. Created by the browser when a page is loaded containing properties that apply to the whole window. It is the top-level object for each document, location, and history object. Because its existence is assumed, you do not have to reference the name of the window when referring to its objects, properties, or methods. For example, the following two lines have the same result (printing a message to the status line): status = "Go away from here." window.status = "Go away from here." A new window is created using the open method: aNewWindow = window.open("URL","Window_Name",["windowFeatures"]) The variable name is used to refer to the window's properties and methods. The window name is used in the target argument of a form or anchor tag. See OBJECTS document and frame; see PROPERTIES defaultStatus, frames, opener, parent, self, status, top, window; see METHODS alert, close, confirm, open, prompt, setTimeout, clearTimeout; see EVENT HANDLERS onLoad and onUnload.

Properties
Properties are used to view or set the values of objects. An object is simply a vague generality until a property is used to define the values which make it specific. action. The action property is a reflection of the action attribute in an HTML <form> tag, consisting of a destination URL for the submitted data. This value can be set or changed before or after the document has been loaded and formatted. In this example, the action for a form called outlineForm is set to the URL contained in the variable outlineURL. outlineForm.action=outlineURL Property of form. See PROPERTIES encoding, method, target.

alinkColor. The color of a link after the mouse button is depressed--but before it's released--and expressed as a hexadecimal RGB triplet or string literal. It cannot be changed after the HTML source is processed. Both of these examples set the color to alice blue. document.alinkColor="aliceblue" document.alinkColor="F0F8FF" Property of document. See PROPERTIES bgColor, fgColor, linkColor, vlinkColor. anchors. An array of all defined anchors in the current document. If the length of an anchor array in a document is 5, then the anchors array is represented as document.anchors[0] through document.anchors[4]. Property of document. See anchor OBJECT; see PROPERTIES length and links. appCodeName. Returns a read-only string with the code name of the browser. document.write("The code name of your browser is " + navigator. appCodeName) For Internet Explorer, this returns: The code name of your browser is Microsoft Internet Explorer 3.0A Property of navigator. See PROPERTIES appName, appVersion, userAgent. appName. Returns a read-only string with the name of the browser. Property of navigator. See PROPERTIES appCodeName, appVersion, userAgent. appVersion. Returns a string with the version information of the browser in the format "releaseNumber (platform; country)." For a release of Internet Explorer 3.0: document.write(navigator.appVersion) returns 3.0 (Win95; U) This specifies IE 3.0 running on Windows 95. The U country code specifies a U.S. release, while an I would indicate an international release. Property of navigator. See PROPERTIES appName, appCodeName, userAgent. bgColor. The document background color expressed as a hexadecimal RGB triplet or string literal. It can be reset at any time. Both of these examples set the background to alice blue.

document.bgColor = "aliceblue" document.bgColor = "F0F8FF" Property of document. See PROPERTIES alinkColor, fgColor, linkColor, vlinkColor. checked. A Boolean value (true or false), indicating whether a check box or radio button is selected. The value is updated immediately when an item is checked. It's used in the following form: formName.checkboxName.checked formName.radioButtonName[index].checked Property of checkbox and radio. See defaultChecked PROPERTY. cookie. String value of a small piece of information stored by the browser in a client-side cookies folder or file. The value stored in the cookie is found using substring, charAt, IndexOf, and lastIndexOf. For more information, see the discussion under TERMS. Property of document. See hidden OBJECT. defaultChecked. A Boolean value (true or false) indicating whether a check box or radio button is checked by default. Setting a value to defaultChecked can override the checked attribute of a form element. The following section of code will reset a group of radio buttons to its original state by finding and setting the default button: for (var i in menuForm.choices) { if (menuForm.choices[i].defaultChecked) { menuForm.choice[i].defaultChecked = true } } Property of checkbox and radio. See form OBJECT; see checked PROPERTY. defaultSelected. A Boolean value (true or false) representing the default state of an item in a form-select element. Setting a value with this property can override the selected attribute of an <option> tag. The syntax is identical to defaultChecked. Property of options. See PROPERTIES index, selected, selectedIndex. defaultStatus. The default message displayed in the status bar at the bottom of a browser window when nothing else is displayed. This is preempted by a priority or transient message, such as a mouseOver event with an anchor. For example: window.defaultStatus = "Welcome to my home page" displays the welcome message while the mouse is not over a link, or Internet Explorer is not performing an action that it needs to notify the user about.

Property of window. See status PROPERTY. defaultValue. The initial contents of hidden, password, text, textarea, and string form elements. For password elements, it is initially set to null for security reasons, regardless of any set value. Property of hidden, password, text, textarea. See value PROPERTY. e. The base of natural logarithms, also known as Euler's constant. The value is approximately 2.718. Property of Math. See PROPERTIES LN2, LN10, LOG2E, LOG10E, PI, SQRT1_2, SQRT2. elements. An array of objects containing form elements in HTML source order. The array index begins with zero and ends with the number of form elements-1. Property of form. See elements OBJECT. encoding. Returns a string reflecting the MIME-encoding type, which is set in the enctype attribute of an HTML <form> tag. Property of form. See PROPERTIES action, method, target. fgColor. The color of foreground text represented as a hexadecimal RGB triplet or a string literal. This value cannot be changed after a document is processed. It can take two forms: document.fgColor="aliceblue" document.fgColor="F0F8FF" Property of document. See PROPERTIES alinkColor, bgColor, linkColor, vlinkColor; see fontcolor METHODS. forms. An array of objects corresponding to named forms in HTML source order and containing an entry for each form object in a document. Property of document. See form object; see length property. frames. An array of objects corresponding to child frame windows created using the <frameset> tag. To obtain the number of child frames in a window, use the length property. Property of window. See frame object; see length property. hash. Returns a string with the portion of an URL beginning with a hash mark (#), which denotes an anchor name fragment. It can be used to set a hash property, although it is safest to set the entire URL as an href property. An error is returned if the hash isn't found in the current location. Property of link and location. See anchor OBJECT; see PROPERTIES host, hostname, href, pathname, port, protocol, search properties. host. Returns a string formed by combining the hostname and port properties of an URL, and provides a method for changing it. location.host = "www.montna.com:80" Property of link and location. See PROPERTIES hash, hostname, href, pathname, port, protocol, search.

hostname. Returns or changes a string with the domain name or IP address of an URL. Property of link and location. See PROPERTIES hash, host, href, pathname, port, protocol, search. href. Returns a string with the entire URL. All other location and link properties are substrings of href, which can be changed at any time. Property of link and location. See PROPERTIES hash, host, hostname, pathname, port, protocol, search. index. Returns the index of an option in a select element with zero being the first item. Property of options. See PROPERTIES defaultSelected, selected, selectedIndex. lastModified. A read-only string containing the date that the current document was last changed, based on the file attributes. The string is formatted in the standard form used by JScript (see Date object). A common usage is: document.write("This page last modified on " + document. lastModified) Property of document. length. An integer reflecting a length- or size-related property of an object. Object history string radio Property Measured Length of the history list Integer length of the string; zero for a null string Number of radio buttons

anchors, forms, Number of elements frames, links, in the array options

Property of anchors, elements, forms, frame, frames, history, links, options, radio, string, window. linkColor. The hyperlink color displayed in the document, expressed as a hexadecimal RGB triplet or as a string literal. It corresponds to the link attribute in the HTML <body> tag, and cannot be changed after the document is processed. Property of document. See PROPERTIES alinkColor, bgColor, fgColor, vlinkColor. links. An array representing link objects defined in HTML using <a href=URL> tags with the first link identified as document.links[0]. See link object. See PROPERTIES anchors and length. LN2. A constant representing the natural logarithm of 2 (approximately 0.693). Property of Math. See PROPERTIES E, LN10, LOG2E, LOG10E, PI, SQRT1_2, SQRT2.

LN10. A constant representing the natural logarithm of 10 (approximately 2.302). Property of Math. See PROPERTIES E, LN2, LOG2E, LOG10E, PI, SQRT1_2, SQRT2. location. Returns a string with the URL of the current document. This read-only property (document.location) is different from the location object's properties (window. location.propertyName), which can be changed. Property of document. See location OBJECT. LOG2E. A constant representing the base 2 logarithm of e (approximately 1.442). Property of Math. See PROPERTIES E, LN2, LN10, LOG10E, PI, SQRT1_2, SQRT2. LOG10E. A constant representing the base 10 logarithm of e (approximately .434). Property of Math. See PROPERTIES E, LN2, LN10, LOG2E, SQRT1_2, SQRT2. method. Reflects the method attribute of an HTML <form> tag: either <GET> or <POST>. It can be set at any time. The first function returns the current value of the form object, while the second function sets the method to the contents of newMethod. function getMethod(formObj) { return formObj.method } function setMethod(formObj,newMethod) { formObj.method = newMethod } Property of form. See PROPERTIES action, encoding, target. name. Returns a string with the name attribute of the object. This is the internal name (set using the HTML NAME attribute) for button, reset and submit objects, not the on-screen label. For example, after opening a new window with indexOutline = window.open("http://www. wossamatta.com/outline.html","MenuPage") and issuing the command document. write(indexOutline.name), JScript returns "MenuPage", which was specified as the name attribute. Property of button, checkbox, frame, password, radio, reset, select, submit, text, textarea, window. See value PROPERTY. opener. Returns the window object from which the current window was opened. For example, if window A issues a window.open() call to create window B, then the value of document. opener in window B is "A." Note: This property is supported only under Internet Explorer at this time. Do not use this property if you want to maintain compatibility with Netscape's JavaScript. Property of window. See also parent and top. options. An array of option objects created by a select form element. The first option's index is zero, the second is 1, and so on. See select OBJECT.

parent. Refers to the calling document in the current frame created by a <frameset> tag. Using parent allows access to other frames created by the same <FRAMESET> tag. For example, two frames invoked are called "index" and "contents." The "index" frame can write to the "contents" frame using the syntax: parent.contents.document.write("Kilroy was here.") Property of frame and window. pathname. Returns the path portion from an URL. Although the pathname can be changed at any time, it is always safer to change the entire URL at once using the href property. Property of link and location. See PROPERTIES hash, host, hostname, href, port, protocol, search. PI. Returns the value of pi (approximately 3.1415927). This is the ratio of the circumference of a circle to its diameter. Property of Math. See PROPERTIES E, LN2, LN10, LOG2E, LOG10E, SQRT1_2, SQRT2. port. Returns the port number of an URL address, which is a substring of the host property in href. Property of link and location. See PROPERTIES hash, host, hostname, href, pathname, protocol, search. protocol. Returns a string with the initial portion of the URL, up to and including the colon, which indicates the access method (http, ftp, mailto, and so on). Property of link and location. See PROPERTIES hash, host, hostname, href, pathname, port, search. referrer. Returns a read-only URL of the document that called the current document. In conjunction with a CGI script, it can be used to keep track of how users are linked to a page. document.write("You came here from a page at " + document.referrer) Property of document. search. Returns a string containing any query information appended to an URL. Property of link and location. See PROPERTIES hash, host, hostname, href, pathname, port, protocol. selected. Returns a Boolean value (true or false) indicating the current state of an option in a select object. The selected property can be changed at any time, and the display will immediately update to reflect the new value. The selected property is useful for select elements that are created using the multiple attribute. Using this property, you can view or change the value of any element in an options array without changing the value of any other element in the array. Property of options. See PROPERTIES defaultSelected, index, selectedIndex. selectedIndex. Returns an integer specifying the index of a selected item. The selectedIndex property is useful for select elements that are created without using the multiple attribute. If

selectedIndex is evaluated when the multiple option is selected, the property returns the index of the first option only. Setting the property clears any other options that are selected in the element. Property of select, options. See PROPERTIES defaultSelected, index, selected. self. Refers to the current window or form, and is useful for removing ambiguity when dealing with window and form properties with the same names. Property of frame and window. See window PROPERTY. SQRT1_2. The square root of 1/2, also expressed as the inverse of the square root of 2 (approximately 0.707). Property of Math. See PROPERTIES E, LN2, LN10, LOG2E, LOG10E, PI, SQRT2. SQRT2. The square root of 2 (approximately 1.414). Property of Math. See properties E, LN2, LN10, LOG2E, LOG10E, PI, SQRT1_2. status. Specifies a priority or transient message to display in the status bar at the bottom of the window, usually triggered by a mouseOver event from an anchor. To display when the mouse pointer is placed over a link, the usage is: <A anchor definition onMouseOver="window.status='Your message.'; return true">link</A> Note the use of nested quotes and the required return true statement at the end of the event handler. Property of window. See defaultStatus PROPERTY. target. A string specifying the name of a window for responses to be posted to after a form is submitted. For a link, target returns a string specifying the name of the window that displays the content of a selected hypertext link. homePage.target = "http://www.wossamatta.com/" Property of form, link, location. See PROPERTIES action, encoding, method. text. Returns the value of text following the <option> tag in a select object. It can also be used to change the value of the option, with an important limitation--while the value is changed, its appearance on-screen is not. Property of options. title. Returns the read-only value set within HTML <title> tags. If a document doesn't include a title, the value is null. Property of document. top. The topmost window, called an ancestor or Web browser window, that contains frames or nested framesets. Property of window. userAgent. Header sent as part of HTTP protocol from client to server to identify the type of client.

Internet Explorer currently returns the string "Mozilla/2.0 (compatible; MSIE 3.0A; Windows 95)" on a Windows 95 platform. Property of navigator. See PROPERTIES appName, appVersion, appCodeName. value. The value of an object depends on the type of object it is applied to. Object checkbox radio select password Value Attribute On if item is selected, off if not String form of value Reflection of option value Return a valid default value, but an encrypted version if modified by the user

button, reset, Value attribute that appears on submit screen, not the button name

hidden, text, Contents of the field textarea

Changing the value of a text or textarea object results in an immediate update to the screen. All other form objects are not graphically updated when changed. Property of button, checkbox, hidden, options, password, radio, reset, submit, text, textarea. For password, text, and textarea, see defaultValue PROPERTY. For button, reset, and submit, see name PROPERTY. For options, see PROPERTIES defaultSelected, selected, selectedIndex, text. For checkbox and radio, see PROPERTIES checked and defaultChecked. vlinkColor. Returns or sets the color of visited links using hexadecimal RGB triplets or a string literal. The property cannot be set after the document has been formatted. To override the browser defaults, color settings are used with the onLoad event handler in the <BODY> tag: <BODY onLoad="document.vlinkColor='aliceblue'"> Property of document. See PROPERTIES alinkColor, bgColor, fgColor, linkColor. window. A synonym for the current window, used to remove ambiguity between a window and form object of the same name. While it also applies to the current frame, it is less ambiguous to use the self property. Property of frame and window. See self PROPERTY.

Methods
Methods are functions and procedures used to perform an operation on an object, variable, or

constant. With the exception of built-in functions, methods must be used with an object: object.method() Even if the method does not require any arguments, the parentheses are still required. The object that utilizes the method is listed after the definition as "Method of object," followed by any cross-references to other methods. Stand-alone functions that are not used with objects are indicated with an asterisk (*). abs. Returns the absolute (unsigned) value of its argument. document.write(Math.abs(-10)); document.write(Math.abs(12)) The above examples return 10 and 12, respectively. Method of Math. acos. Returns the arc cosine (from zero to pi radians) of its argument. The argument should be a number between -1 and 1. If the value is outside the valid range, a zero is returned. Method of Math. See METHODS asin, atan, cos, sin, tan. alert. Displays a JScript alert dialog box with an OK button and a user-defined message. Before the user can continue, he or she must press the OK button. Method of window. See METHODS confirm and prompt. anchor. Used with write or writeln methods, anchor creates and displays an HTML hypertext target. The syntax is: textString.anchor(anchorName) where textString is what the user sees, and anchorName is equivalent to the name attribute of an HTML <anchor> tag. Method of string. See link METHOD. asin. Returns the arc sine (between -pi/2 and pi/2 radians) of a number between -1 and 1. If the number is outside the range, a zero is returned. Method of Math. See METHODS acos, atan, cos, sin, tan. atan. Returns the arc tangent (between -pi/2 and pi/2 radians) of a number between -1 and 1. If the number is outside the range, a zero is returned. Method of Math. See METHODS acos, asin, cos, sin, tan. back. Recalls the previous URL from the history list. This method is the same as history.go(-

1). Method of history. See METHODS forward and go. big. Formats a string object as a big font by encasing it with HTML <big> tags. Both of the following examples result in the same output--displaying the message "Welcome to my home page" in a big font: var welcomeMessage = "Welcome to my home page." document.write(welcomeMessage.big()) <BIG> Welcome to my home page.</BIG> Method of string. See METHODS fontsize, small. blink. Formats a string object as a blinking line by encasing it with HTML <blink> tags. Both of the following examples produce a flashing line that says "Notice": var attentionMessage = "Notice" document.write(attentionMessage.blink()) <BLINK>Notice</BLINK> Method of string. See METHODS bold, italics, strike. blur. Removes focus from the specified form element. For example, the following line removes focus from feedback: feedback.blur() assuming that feedback is defined as: <input type="text" name="feedback"> Method of password, select, text, textarea. See METHODS focus and select. bold. Formats a string object in bold text by encasing it with HTML <b> tags. Method of string. See METHODS blink, italics, strike. ceil. Returns the smallest integer greater than, or equal to, its argument. For example: Math.ceil(1.01) returns a 2. Method of Math. See floor METHOD. charAt. Returns the character from a string at the specified index. The first character is at position zero and the last at length -1.

var userName = "Bobba Louie" document.write(userName.charAt(4) returns an "a". Method of string. See METHODS indexOf and lastIndexOf. clear. Clears the contents of a window, regardless of how the window was filled. Method of document. See METHODS close, open, write, writeln. clearTimeout*. Cancels a timeout set with the setTimeout method. A timeout is set using a unique timeout ID, which must be used to clear it: clearTimeout(waitTime) Method of frame and window. See setTimeout METHOD. click. Simulates a mouse click on the calling form element with the effect dependent on the type of element. Form Element Radio Checkbox Action Selects radio button. Marks checkbox and sets value to on.

Button, Reset, and Submit Same as clicking button.

Method of button, checkbox, radio, reset, submit. close. For a document object, closes the current output stream and forces its display. It also stops the browser icon animation and displays Done in the status bar. For a window object, closes the current window. As with all window commands, the window object is assumed. For example: window.close() close() self.close() all close the current window. Method of document and window. See METHODS clear, open, write, writeln. confirm. Displays a JScript confirmation dialog box with a message and buttons for OK and Cancel. Confirm returns a true if the user selects OK and false for Cancel. The following example loads a new window if the user presses OK: if (confirm("Are you sure you want to enter.") {

tourWindow = window.open("http:\\www.haunted.com\","hauntedhouse") } Method of window. See METHODS alert and prompt. cos. Returns the cosine of the argument. The angle's size must be expressed in radians. Method of Math. See METHODS acos, asin, atan, sin, tan. escape*. Returns ASCII code of its argument based on the ISO Latin-1 character set in the form %xx, where xx is the ASCII code. It is not associated with any other object, but is actually part of the JScript language. See unescape METHOD. eval*. This built-in function takes a string or numeric expression as its argument. If a string, it attempts to convert it to a numeric expression. Eval then evaluates the expression and returns the value. var x = 10 var y = 20 document.write(eval("x + y")) This method can also be used to perform JScript commands included as part of a string, as in this example: var doThis = "if (x==10) { alert("Your maximum has been reached") } function checkMax () { x++; eval(doThis) } This can be useful when converting a date from a form (always a string) into a numerical expression or number. exp. Returns e (Euler's constant) to the power of the argument. Method of Math. See METHODS log and pow. fixed. Formats the calling string into a fixed-pitch font by encasing it in HTML <tt> tags. Method of string. floor. Returns the integer less than, or equal to, its argument. For example: Math.floor(2.99) returns a 2. Method of Math. See ceil METHOD. focus. Navigates to a specific form element and gives it focus. From that point, a value can be

entered by JScript commands or the user can complete the entry. Method of password, select, text, textarea. See METHODS blur and select. fontcolor. Formats the string object to a specific color expressed as a hexadecimal RGB triplet or a string literal, similar to using <font color=color>. Method of string. fontsize. Formats the string object to a specific font size: one of the seven defined sizes using an integer through the <fontsize=size> tag. If a string is passed, then the size is changed relative to the value set in the <basefont> tag. Method of string. See METHODS big and small. forward. Loads the next document on the URL history list. This method is the same as history.go (1). Method of history. See methods back and go. getDate. Returns the day of the month as an integer between 1 and 31. Method of Date. See setDate method. getDay. Returns the day of the week as an integer from zero (Sunday) to six (Saturday). There is no corresponding setDay method because the day is automatically computed when the date value is assigned. Method of Date. getHours. Returns the hour of the day in 24-hour format, from zero (midnight) to 23 (11 P.M.). Method of Date. See setHours METHOD. getMinutes. Returns the minutes as an integer from zero to 59. Method of Date. See setMinutes METHOD. getMonth. Returns the month of the year as an integer between zero (January) and 11 (December). Method of Date. See setMonth METHOD. getSeconds. Returns the seconds as an integer from zero to 59. Method of Date. See setSeconds METHOD. getTime. Returns an integer representing the current value of the date object. The value is the number of milliseconds since midnight, January 1, 1970 (known as The Epoch). This value can be used to compare the length of time between two date values. For functions involving computation of dates, it is useful to define variables giving the minutes, hours, and days in milliseconds: var dayMillisec = 1000 * 60 * 60 * 24 //1,000 milliseconds x 60 sec x 60 min x 24 hrs var hourMillisec = 1000 * 60 * 60 //1,000 milliseconds x 60 sec x 60 min var minuteMillisec = 1000 * 60 //1,000 milliseconds x 60 sec Method of Date. See setTime METHOD. getTimezoneOffset. Returns the difference in minutes between the client machine and Greenwich

Mean Time. This value is a constant except for daylight savings time. Method of Date. getYear. Returns the year of the date object minus 1900. For example, 1996 is returned as 96. Method of Date. See setYear METHOD. go. Loads a document specified in the history list relative to the current position on the list. If the value given to go is out of range (before the beginning of the history list, or after its end) the nearest valid value is used. Method of history. See METHODS back and forward. indexOf. Returns the location of a specific character or string, starting the search from a specific location. The first character of the string is at location zero and the last is at location length-1. The syntax is: stringName.indexOf([character|string], [startingPoint]) The startingPoint is zero by default. Method of string. See METHODS charAt and lastIndexof. italics. Formats a string object into italics by encasing it an HTML <I> tag. Method of string. See METHODS blink, bold, strike. lastIndexOf. Returns the index of a character or string in a string object by looking backwards from the end of the string or from a user-specified index. Method of string. See METHODS charAt and indexOf. link. Creates a hypertext link to another URL by defining the <href> attribute and the text representing the link. Method of string. See anchor METHOD. log. Returns the natural logarithm (base e) of a positive numeric expression. An out-of-range number always gives an error. Method of Math. See METHODS exp and pow. max. Returns the greater of its two arguments. For example: Math.max(1,100) returns 100. Method of Math. See min METHOD. min. Returns the lesser of its two arguments. Method of Math. See max METHOD. open. For a document, opens a stream to collect the output of write or writeln methods. If a document already exists in the target window, then the open method clears it. The stream is ended by using the document.close() method. For a window, it opens a new browser window in a similar fashion to choosing New Window from the File menu. Using the URL argument, it loads a document into the new window; otherwise, the new window is blank. When used as part of an event handler,

the form must include the window object; otherwise, the document.open method is assumed. Window features are defined by a comma-separated list of options with =1 or =yes to enable and =0 or =no to disable. Window features include toolbar, location, directories, status, menubar, scrollbars, resizable, copyhistory, width, and height. Method of document and window. See METHODS clear, close, write, writeln. parse. Takes a date string, such as "Jan 11, 1996", and returns the number of milliseconds since midnight, Jan. 1, 1970. This function can be used to set date values based on string values. When passed a string containing a date, it returns the time value. Because parse is a static function of Date, it is always used as Date.parse() rather than as a method of a created Date object. Method of Date. See UTC METHOD. parseFloat*. Parses a string argument and returns a floating-point number if the first character is a plus sign, minus sign, decimal point, exponent, or a numeral. If it encounters a character other than one of the valid choices after that point, it returns the value up to that location and ignores all succeeding characters. If the first character is not a valid character, parseFloat returns zero. parseInt*. Parses a string argument and returns an integer based on a specified radix or base. A radix of 10 interprets the string as a decimal number, while eight implies an octal number, and 16 a hexadecimal number. Floating-point values are converted to integers. The rules for evaluating the string are identical to parseFloat. See the parseFloat METHOD. pow. Returns the base argument raised to the exponent. Method of Math. See exp and log METHODS. prompt. Displays a prompt dialog box that accepts user input. If an initial value is not specified for inputDefault, the dialog box displays a blank value. Method of window. See alert and confirm METHODS. random. Returns a pseudo-random floating-point number between zero and 1. Method of Math. round. Returns the value of a floating-point argument rounded to the next highest integer if the decimal portion is greater than, or equal to, .5, or the next lowest integer if it is less than .5. Method of Math. select. Selects the input area of a specified form element. Used in conjunction with the focus method, JScript can highlight a field and position the cursor for user input. Method of password, text, textarea. See METHODS blur and focus. setDate. Sets the day of the month. Method of Date. See getDate METHOD. setHours. Sets the hour for the current time. Method of Date. See getHours METHOD.

setMinutes. Sets the minutes for the current time. Method of Date. See getMinutes METHOD. setMonth. Sets the month with an integer from zero (January) to 11 (December). Method of Date. See getMonth METHOD. setSeconds. Sets the seconds for the current time. Method of Date. See getSeconds METHOD. setTime. Sets the value of a Date object. Method of Date. See getTime METHOD. setTimeout*. Evaluates an expression after a specified amount of time, expressed in milliseconds. This is not repeated indefinitely. For example, setting a timeout to three seconds will evaluate the expression once after three seconds--not every three seconds. To call setTimeout recursively, reset the timeout as part of the function invoked by the method. Calling the function startclock in the following example sets a loop in motion that clears the timeout, displays the current time, and sets the timeout to redisplay the time in one second. var timerID = null; var timerRunning = false; function stopclock () { if(timerRunning) cleartimeout(timerID); timerRunning=false; } function startclock () { stopclock(); showtime(); } function showtime () { var now = new Date(); ... document.clock.face.value = timeValue; timerID = setTimeout("showtime()",1000); timerRunning = true; } Method of window. See clearTimeout METHOD. setYear. Sets the year in the current date using an integer representing the year minus 1900. Years before 1970 are not currently permitted. Method of Date. See getYear METHOD. sin. Returns the sine of an argument. The argument is an angle expressed in radians, and the returned value is from -1 to 1. Method of Math. See METHODS acos, asin, atan, cos, tan. small. Formats a string object into a small font using the HTML <small> tag. Method of string. See METHODS big and fontsize. sqrt. Returns the square root of a positive numeric expression. If the argument's value is outside the range, the returned value is zero.

strike. Formats a string object as strikeout text using the HTML <strike> tag. Method of string. See METHODS blink, bold, italics. sub. Formats a string object into subscript text using the HTML <sub> tag. Method of string. See sup METHOD. submit. Performs the same action as clicking a submit button. Method of form. See submit OBJECT; see onSubmit EVENT HANDLER. substring. Returns a subset of a string object based on two indexes. If the indexes are equal, an empty string is returned. Regardless of order, the substring is built from the smallest index to the largest. Method of string. sup. Formats a string object into superscript text using the HTML <sup> tag. Method of string. See sub METHOD. tan. Returns the tangent of an argument. The argument is an angle expressed in radians. Method of Math. See METHODS acos, asin, atan, cos, sin. toGMTString. Converts a date object to a string using Internet Greenwich Mean Time (GMT) conventions. For example, if today is a date object: today.toGMTString() then the string "Mon, 18 Dec 1995 17:28:35 GMT" is returned. Actual formatting may vary from platform to platform. The time and date are based on the client machine. Method of Date. See toLocaleString METHOD. toLocaleString. Converts a date object to a string using the local conventions, such as mm/dd/yy hh: mm:ss. Method of Date. See toGMTString METHOD. toLowerCase. Converts all characters in a string to lowercase. Method of string. See toUpperCase METHOD. toString. Converts an object to a string. In addition to working on the built-in Date and location objects, it will also work with user-defined objects. Method of Date, location. toUpperCase. Converts all characters in a string to uppercase. Method of string. See toLowerCase METHOD. unEscape*. Returns a character based on its ASCII value expressed as a string in the format %xx where xx is a hexadecimal number between 0x0 and 0xFF. See escape METHOD. UTC. Returns the number of milliseconds for a date in Universal Coordinated Time (UTC) since midnight, January 1, 1970. UTC is a static method, and is always used as Date.UTC(), not with a created Date object.

Method of Date. See parse METHOD. write. Writes one or more lines to a document window, and can include HTML tags and JScript expressions, including numeric, string, and logical values. The write method does not add a new line (<br> or \n) character to the end of the output. If called from an event handler, the current document is cleared if a new window is not created for the output. Method of document. See METHODS close, clear, open, writeln. writeln. Writes one or more lines to a document window followed by a new line character; can include HTML tags and JScript expressions, including numeric, string, and logical values. If called from an event handler, the current document is cleared if a new window is not created for the output. Method of document. See METHODS close, clear, open, write.

Event Handlers
Event handlers are where JScript gets its power. By looking for specific user actions, JScript can confirm or act on input immediately, without waiting for server intervention. onBlur. Blurs occur when a select, text, or textarea field in a form loses focus. Event handler of select, text, textarea. See EVENT HANDLERS onChange and onFocus. onChange. A change event happens when a select, text, or textarea element on a form is modified before losing focus. Event handler of select, text, textarea. See EVENT HANDLERS onBlur, onFocus. onClick. Occurs when an object, such as a button or checkbox, is clicked. Event handler of button, checkbox, radio, link, reset, submit. onFocus. A form element receives focus by tabbing to or clicking the input area with the mouse. Selecting within a field results in a select event. Event handler of select, text, textarea. See EVENT HANDLERS onBlur and onChange. onLoad. A load event is created when the browser finishes loading a window or a frame within a <frameset> tag. Event handler of window. See onUnload EVENT HANDLER. onMouseMove. A Microsoft-specific extension of the onMouseOver event. This form of the event permits the event handler to receive the x and y coordinates of the mouse at the time the event occurred, as well as the current state of the mouse button(s) and the shift key. Currently, this event is implemented only for ActiveX controls. See onMouseOver EVENT HANDLER. onMouseOver. Occurs when the mouse pointer is placed over a link object. To function with the status or defaultStatus properties, the event handler must return true. Event handler of link. onSelect. A select event is triggered by selecting some or all of the text in a text or textarea field. Event handler of text, textarea.

onSubmit. Triggered by the user submitting a form. The event handler must return true to allow the form to be submitted to the server. Conversely, it returns false to block the form's submission. Event handler of form. See submit OBJECT and METHOD. onUnload. Occurs when exiting a document. For proper operation, place the onUnload handler in the <body> or <frameset> tags. Event handler of window. See onLoad EVENT HANDLER.

DISCLAIMER

To order books from QUE, call us at 800-716-0044 or 317-361-5400. For comments or technical support for our books and software, select Talk to Us. 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.

Vous aimerez peut-être aussi