Working with Javascript: Introduction

Steve Champeon
2001-01-25
Apple's Internet Developer Site

Introduction

The Web is set to enter its second decade soon, and it's easy to lose track of how much things have changed since the heady, early days. Back then, nearly everything on the Web was plain text, displayed in one or two fonts per platform. Hypertext was the exciting thing; hyper media was still talked about in the same tones as are used nowadays to refer to universal home broadband access or cheap flat panel monitors.

Simply being able to view — from the comfort of your own desktop workstation — scientific papers provided by a server halfway around the world, was a miracle of epic proportions, and was often reason enough to buy a new computer, just so you wouldn't miss out.

Obviously, a lot has changed since the early days. Hypertext is commonplace, usability experts continue to call for the universal recognition of the blue underline as the symbol of a link, and if your company doesn't have a Web site — if only a brochure — it's assumed that you fell asleep sometime during 1995 and never woke up.

Most importantly, however, we now have client-side scripting, thanks to Netscape's introduction of JavaScript in Navigator 2.0. And with the raw, naked power that client-side scripting gives us as developers, we can accomplish almost anything!

Okay, maybe not quite everything. But you can accomplish an astonishing range of things with client-side Javascript that simply can't be done (or can't be done as well) any other way. With JavaScript, we can do everything from image rollovers:

function highlight(name, n) {
document.images[n].src = "/images/" +
name + "_hi.gif";
window.status = name;
}

function lolight(name, n) {
document.images[n].src = "/images/" +
name + ".gif";
}

... to simple client-side form validation:

var quantity =
document.forms['order'].totalQuantity.value;
if( parseInt(quantity) <= 0 ) {
alert("You must specify how
many widgets you want to buy!\n" +
"Sorry, " + quantity + " is
not an acceptable quantity.");
return false;
}

... and on-the-fly interaction with the end user:

var username = "";
if( (username = prompt("What is your name?")) !=
null) {
var browser = navigator.userAgent;
var happy = "Congratulations!
You're using a Macintosh!";
var sorry = "I see you're not using a Macintosh, ";
if( browser.indexOf("Mac") != -1 ) {
alert("Hi, " + username + "! " + happy);
return true;
}
else {
return confirm(sorry + username +
". Do you want to continue anyway?");
}
}

... through dynamic document creation and manipulation:

var mac_styles = '<LINK HREF="mac-styles.css"';
var win_styles = '<LINK HREF="win-styles.css"';
var oth_styles = '<LINK HREF="other.css"';
var styles_end = ' REL="STYLESHEET"
TYPE="text/css">';

document.open("text/html");
if(browser.indexOf("mac") != -1 ) {
document.write(mac_styles);
} else if(browser.indexOf("win") != -1 ) {
document.write(win_styles);
} else {
document.write(oth_styles);
}
document.writeln(styles_end);
document.close();

... and the storage and reuse of the user's preferences:

var favorite_color = get_cookie("fave_color");
if( favorite_color == "blue" ) {
use_blue_background();
} else if( favorite_color == "red" ) {
use_red_background();
} else {
use_default_background();
prompt_user_for_color_preference();
}

... to using dynamic HTML as the basis for a new generation of Web-based graphical user interfaces and applications.

We are entering an age where code that used to be peppered almost exclusively with references to form elements and their values, or calls to document.write() now more closely resembles the pseudo-code used to illustrate accounting concepts to MBAs:

var loan_to_value_pivot = 0.9;
var debt_ratio_low = 28;
var debt_ratio_mid = 33;
var debt_ratio_hi = 36;
var debt_ratio_max = 38;

if((loan_type == "30yearfixed") ||
(loan_type == "15yearfixed")) {
if( use_type == "primaryresidence" ) {
if( loan_to_value <= loan_to_value_pivot ) {
if((monthly_payment_to_income_ratio >=
debt_ratio_mid) ||
(monthly_debt_to_income_ratio >=
debt_ratio_max)) {
fail_prequalification();
return;
}
} else if( loan_to_value > loan_to_value_pivot ) {
if((monthly_payment_to_income_ratio >=
debt_ratio_low) ||
(monthly_debt_to_income_ratio >=
debt_ratio_hi)) {
fail_prequalification();
return;
}
}
} else if( use_type == "secondhome" ) {
if( loan_to_value <= loan_to_value_pivot ) {
if((monthly_payment_to_income_ratio >=
debt_ratio_low) ||
(monthly_debt_to_income_ratio >

debt_ratio_hi)) {
fail_prequalification();
return;
} else {
pass_prequalification();
close_prequalificiation_screen();
proceed_to_loan_application();
}
}
}
}

Nowadays, there are entirely self-contained JavaScript spreadsheet modules, which can be used as components in your Web applications. There are scripts that can be used to determine if a given visitor has the appropriate plugins for your snazzy new Quicktime movie or streaming audio capture of your child's first words. The fact of the matter is that client-side scripting has infiltrated every facet of the online experience, even email. Some browsers' interfaces (most notably Netscape 6 and Mozilla) are even JavaScript-driven.

Of course, as with any relatively new technology, there are the inevitable bugs, cross-platform issues, incompatibilities between software from different vendors claiming to support the same functionality, and the like. Scripts that started out simple, if somewhat exclusionary, like this:

<SCRIPT LANGUAGE="Javascript">

alert("hello, Netscape user!");
</SCRIPT>

<NOSCRIPT>
Hello, non-Netscape user!
Your browser doesn't support this cool feature!
</NOSCRIPT>

have become classic demonstrations of how to bury the intent of the original programmer beneath multiple branches, tests, and workarounds:

function contrived(example) {
if( is_ie4 ) {
// check for platform
if( is_win ) {
// do this the Windows-compatible way
} else if( is_mac ) {
// do this the Macintosh way
if( javaEnabled() ) {
// use Java
} else {
// don't use Java
if( navigator.plugins["QuickTime"] !=
null ) {
// use QuickTime
} else if(navigator.plugins["Shockwave"] !=
null ) {
// use Shockwave
} else {
// fail with an error
alert("Your plugins could
use some updating!");
}
}
} else {
// must be solaris?
}
} else if( is_ie5 ) {
if( document.getElementById ) {
// use the W3C DOM
} else if( document.all ) {
// use the IE DOM
}
} else if( is_ns4 ) {
// use the Netscape Layers DOM
} else if( is_ns3 ) {
// use document.write() to create the entire page
} else if( ... ) {
// this is silly. what were we doing, again?
}
}

There are fundamental characteristics of the technology that make a black art out of debugging even the simplest scripts. The march of progress has its stragglers, and the thrill of learning the power to be had in the latest versions of the browsers is offset by the realization that a large part of your audience has yet to download and install those browsers, leaving it up to you to decide how to take advantage of new features while still accommodating your legacy audience.

Fortunately, we're here to help. We believe that it is essential that the Web both continue to reach everyone with a browser and continue to grow and expand its capabilities, achieving the awesome potential suggested by those early days of simple text documents. Universal access means that developers have a responsibility to ensure that their scripts work across platform and browser, while providing reasonable fallback functionality for those who have disabled JavaScript or cookies out of concern for their privacy or their company's security. And, of course, we're interested in helping you make your Web site work properly on the best platform, in the best browsers currently shipping.

In the coming months, be sure to check out the site for clear and detailed articles discussing the issues we outline above. We welcome your feedback and suggestions for new articles as well, so don't be shy. This is your resource. Use it.