Chapter 3
Style
CONTENTS
HTML enables you to take plain text and turn it into an attractively
laid out document. It also lets you turn the text into an ugly mess that
no one would want to read. JavaScript confers an even greater ability to
create a spectacular document, and an even greater ability to create a
hideous page that no one will want to read. Using JavaScript, you can even
crash the browser. This chapter explains how to use JavaScript judiciously
so your Web pages both look nice and run smoothly.
Image
is everything
Your Web pages are your personal ambassadors to the world. They make
a statement about you. Naturally, you can't control everyone's reaction
to your pages; some people simply are not going to take an interest in
what you have to say. But you can take simple steps in terms of the content
of your pages (what you say) and in terms of the presentation of your pages
(how you say it) to maximize the impact you want your pages to have.
Content
What you say and how you say it makes a big difference in how readers
view your pages. Simple mistakes in the content-particularly the text portions
of your page-can lose readers or make a poor impression, and such mistakes
are not that difficult to prevent.
Speling
"Speling"? That really looks bad, doesn't it? If you're writing
the text in your pages in your native language (people tend to cut you
some slack otherwise), check your spelling. Misspelled words convey a bad
impression, making you look sloppy, careless, ignorant-take your pick.
If you make spelling mistakes, the best you can hope for is that your readers
don't notice or don't care.
So check the spelling in your pages before you load them onto your server
for public consumption. Most word processors have built-in or bundled spell
checking capabilities. Most of them can learn to accept and ignore HTML
tags. Some online services will check the spelling of your pages within
seconds; these services already know to overlook HTML tags.
If you have a lot of JavaScript code in your pages, the spell checker
will probably go ballistic over the code. It will not recognize your variable
or function names unless you've entered them into the spell checker's dictionary,
which is a practice I do not endorse. (It tends to clutter up the dictionary,
and unless you're using the spell checker strictly for your Web pages,
you've just told the spell checker to ignore what may well be typos in
a business letter.) The solution is to make a copy of your page and remove
the contents of the <SCRIPT> element before running the copy through
a spell checker. Because you'll be making changes by hand, this should
be an iterative process (you'll repeat these steps until the text of your
page is clean). Of course, you can avoid the iterative process if you have
access to software that will merge changes automatically. Here is what
you should do:
- Make a copy of your page
- Remove the JavaScript code from the copy.
- Run the copy through a spell checker.
- If the spell checker reveals spelling errors, fix them in the original
page. Otherwise, you're done.
- Go back to step 1. This will ensure that you've caught all of the mistakes.
Sometimes you may want to deliberately use misspelled words, as in the
heading of this section. As long as the typical reader will realize that
the word is deliberately misspelled, this is probably not a problem.
You may also use misspelled words in quotations that contain misspellings.
To handle this situation, first enclose the quotation within an appropriate
element, such as <CITE>, so the reader has a clue that the enclosed
text is a quotation. Second, you may want to place the Latin word "sic"
in parentheses following the misspelled word. This tells your readers that
you are quoting a misspelled word rather than misspelling the word yourself.
Unless you want your readers to instantly consider you an adolescent
who finally cracked mommy or daddy's password, avoid misspellings such
as "kewl" and "dood" and "warez." Also try
to remember the difference between the letter "O" and the number
"0." They are not interchangeable.
Grammar
Poor grammar can alienate your readers as much as poor spelling can.
Unfortunately, it's a little bit more difficult to check grammar than it
is to check spelling. Grammar checking software is less common than spell
checking software. Grammar also includes many gray areas, and grammar checking
software is more likely than spell checking software to miss errors
and falsely label valid text as erroneous. However, few readers will recognize
subtle errors, and the rules of grammar often allow for exceptions.
A good approach is to try to catch the big errors. Don't mix up singular
and plural in the subject and predicate of a sentence. An old rock standard
from the early '60s contains a line, "I knew we was falling in love,"
that has the same effect on me as fingernails on a chalkboard. Although
that particular error may not bother you, it really stands out in print.
Don't confuse possessive words with contractions that involve the word
"is," especially "its" (which means belonging to or
pertaining to "it") and "it's" (which means "it
is"). Dust off a copy of Strunk and White's Elements of Style,
or check it out on the Web.
Adult material
Adults built the World Wide Web for adults. It was never intended to
be a medium for children. Nevertheless, it has become a medium that children
can and do use.
Does this mean that your pages should be free of content that may not
be appropriate for children? Personally, I don't think that's necessary.
I don't carry this kind of material in my own pages, primarily because
it attracts a lot of hits. I have no compelling reason to degrade my Web
space provider's performance or to pay extra for the privilege of doing
so.
Still, you may choose to include such material on your page. If you
do, it is a common courtesy to have a "gatekeeper" page warning
readers that they're about to access material that may not be appropriate
for children.
After going through the gatekeeper page, the reader has the protected
page's URL. At this point, the reader can bookmark the URL or publish the
URL to others, who can then bypass the gatekeeper and go straight to the
protected page. JavaScript provides a mechanism for ensuring that readers
go through your gatekeeper first: the document object's referrer property.
The referrer property provides you with a read-only string containing
the full URL of the page that the reader just came from. When your page
is loaded, it can check the referrer property to see if the reader loaded
this page from the gatekeeper page and refuse to load the restricted contents.
Here's a sample gatekeeper page, referrer.htm:
<HTML>
<HEAD>
<TITLE>Gatekeeper</TITLE>
</HEAD>
<BODY>
<A HREF="protect.htm">Click here</A>
</BODY>
</HTML>
This very simple page's sole purpose is to provide access to the adult
material in protect.htm.
Here's protect.htm:
<HTML>
<HEAD>
<TITLE>Protected Material</TITLE>
<SCRIPT>
<!-- beginning of script
if (document.referrer != "file:///C|/JVSCRIPT.MOS/REFERRER.HTM")
{
history.back();
}
else
{
// we got here from the correct URL
}
// end of script -->
</SCRIPT>
</HEAD>
<BODY>
<!-- protected material goes here -->
</BODY>
</HTML>
This protection is very simple: If the referrer property doesn't match
the URL of the gatekeeper page, the browser bounces the reader straight
back to where he or she came from. You could enhance this protection scheme
by using the alert() method to display a message to the reader, explaining
that he or she cannot access this page directly, but must first pass through
the gatekeeper page.
To get the URL of the referring page, I originally included code in
protect.htm that wrote the contents of the referrer property to the page:
document.write(document.referrer);
If I placed these pages on my Web space provider, I would comment out
the history.back() call and reintroduce the document.write(document.referrer)
call. By doing so, I make sure I have the correct format for referrer.htm's
URL.
Presentation
The best content in the world is useless if you're the only one who
can see it. It's easy to forget that not everyone is using a system exactly
like yours. Even if your system presents your page the way you want it
to, not everyone else will necessarily see what you want them to see.
Not all browsers support JavaScript
It's a sad but true fact that not all browsers support JavaScript. Readers
using popular browsers such as NCSA Mosaic will not benefit from your JavaScript
expertise. Unless you want to alienate those readers, you need to be sensitive
to the needs of the Netscape-deficient. Two major errors to avoid are littering
the screen with JavaScript code and leaving a blank page for the reader
to ponder.
Hide your code The casual reader is probably not interested
in your Java-Script code. The reader using a browser that can't interpret
JavaScript code is even less likely to be interested in it. Hide your code.
Embedding JavaScript within comment tags is an important step in hiding
the code. Browsers that don't support JavaScript will display the JavaScript
code that lies within the <SCRIPT> element as plain text. If you
place this code within comment tags it won't be displayed. Immediately
following the <SCRIPT> tag, insert the beginning of an HTML comment
(<!--). Netscape will ignore it; other browsers will see that it is
the start of a comment.
Just before the </SCRIPT> tag, you need to end the comment. There
are two ways you can do this; you can use the method you prefer.
The first way of ending a comment is to place a complete HTML comment
at the end of the JavaScript code, like this:
<!-- end of script --></SCRIPT>
To Netscape, this looks like a new comment followed by the </SCRIPT>
end tag. Other browsers ignore the <!-- and see the --> as the end
of the comment that was started at the beginning of the <SCRIPT>
element.
The other way of ending a comment is to begin a JavaScript one-line
comment-the kind that starts with // and ends with the end of the source
line. Just make sure that the --> is at the end of the comment. As with
the first method, browsers that don't support JavaScript will close the
comment that was begun after the <SCRIPT> tag when they see the -->
at the end of the comment. Netscape sees it as a routine JavaScript comment.
The only drawback to this technique is that it forces the </SCRIPT>
tag to be on the next source line. If it were on the same line as the one-line
comment, it would become part of the comment.
It's easy to hide your JavaScript code. However, your own code could
sabotage your efforts to make it invisible. Here are two steps to take
to prevent this unwitting sabotage:
First, don't use the decrement operator (--). Some browsers see the
double hyphen as the end of the comment; everything following the decrement
operator may show up on the reader's screen. Instead, use the -= operator
with an operand of 1, like this:
x -= 1;
Second, avoid using the > character in your script. Some browsers
treat the > character as the end of the comment regardless of whether
it's preceded by --.
The > symbol will show up in your JavaScript code as the greater
than operator and as the end of tags. The first usage is trivial to fix;
instead of
x > y
rewrite your code as:
y < x
The two expressions are identical in their value: true if x is greater
than y and false if x is less than or equal to y.
The second usage is a little harder to fix. Suppose you write a tag
like this:
document.write("<TITLE>Visible code under some browsers</TITLE>");
First, you need to create a string that contains a single > character,
like this:
var tagEnd = unescape("%3E");
Then, in subsequent lines, substitute your string as needed, like this:
document.write("<TITLE" + tagEnd + "Invisible code under all browsers</TITLE" + tagEnd);
Try to see your document their way When creating Web
pages, it's important to know how they'll look to others. You can download
many of the major browsers, such as Mosaic, for your favorite platform
and purchase costs are not very high. Get the major browsers and load your
pages into them so you can get a sense of how your pages will look to your
readers.
Don't forget to use the <NOFRAME> element if your pages use frames.
This element allows you to include text that frame-ignorant browsers will
display. The text can be as elaborate as a full HTML 2.0 compliant <BODY>
element, or it can be as simple as an explanation like this:
<NOFRAME>
We are sorry to inform you that you have accessed a page that you need Netscape 2.0
to fully appreciate. You are not using Netscape 2.0; if you were, you wouldn't
see this text. <A HREF="your HTML 2.0 version of this page">Here</A> is an
equivalent page that doesn't require Netscape. Perhaps you should consider
downloading a copy of <A HREF="Netscape's URL for downloading the latest version
of Netscape Navigator">Netscape Navigator</A>.
</NOFRAME>
Finally, some browsers, such as lynx, don't know what to do with images.
Don't forget to include the ALT attribute in all of your inline images;
it lets you define alternate text that can be displayed in lieu of your
image.
Not all platforms are created equal, part 1
Not all platforms support 24-bit color in a 1280x1024 screen resolution.
If you create a page that relies on having lots of screen real estate and
thousands of colors, you will disappoint a lot of readers. Of all the platforms
that support the Netscape Navigator, the title of "least forgiving"
probably has to go to Windows 3.1, running in 640x480 pixel mode, using
16 colors.
Recall that colors are expressed as a red-green-blue triplet, with 8
bits per component. That's 24 bits. That's wonderful for people with state-of-the-art
video, and it's not too bad even for people whose systems can only eke
out 8 bits (256 colors). But for video that is restricted to 4 bits for
color, it's a challenge. How many colors are you using? Before you answer
that, don't forget the colors in your inline GIF and JPEG images. Try out
your page on a 16-color system. How does it look? More importantly, can
you read it?
Okay, maybe you don't care about those cheapskates who can't be bothered
to upgrade their systems with a decent video card and monitor. After all,
prices are dropping. What's the problem?
Well, you still need to deal with the 640x480 pixel straightjacket,
and that's not necessarily an artifact of a low-end system. The better
the screen resolution, the smaller the pixels, and the smaller the pixels,
the harder it is to read text. A lot of people suffer from a medical condition
called presbyopia. If you're pushing 40 or you've passed that milestone,
you probably know what this is. It's why you wear reading glasses, or bifocals,
or progressive lenses. You can't focus on small print as you used to. The
rest of you whippersnappers out there, heh heh, it's waiting for you.
So what does this mean to you as a page author? It means you want to
be careful about creating documents with lots of frames subdividing the
canvas. If I, the reader, have to squint to see your frame contents, or
scroll madly in all directions, I don't care if you have the plans for
world peace in your page. I'm not going to go to the trouble of trying
to read it! Bottom line: Keep your pages simple. Keep the clutter to a
minimum. To test your pages, here's a very simple page I call "The
Bed of Procustes":
<HTML>
<HEAD>
<TITLE>The Bed of Procustes</TITLE>
<SCRIPT>
<!-- Hide from primitive browsers
function putToBed(form)
{
// get the data from the form...
var url = form.urlWidget.value;
var width = form.widthWidget.value;
var height = form.heightWidget.value;
// create the command. specifying the url in the command seems to be
// a problem, so the window is created empty, then loaded
var command = "window.open('', 'noname',";
command += " 'toolbar=yes,location=yes,directories=yes,status=yes,";
command += "menubar=yes,scrollbars=yes,resizable=no,width=" + width;
command += ",height=" + height + "')";
// create the window
var bed = eval(command);
// do it twice for brain-damaged platforms
bed = eval(command);
// load it
bed.location.href = url;
// we're not really submitting a form, so return false
return false;
}
//-->
</SCRIPT>
</HEAD>
<BODY>
<FORM ONSUBMIT="putToBed(this)">
Window Width: <INPUT TYPE=TEXT SIZE=5 NAME="widthWidget">
Window Height: <INPUT TYPE=TEXT SIZE=5 NAME="heightWidget">
<BR>
URL To Be Loaded: <INPUT TYPE=TEXT SIZE=50 NAME="urlWidget">
<BR>
<INPUT TYPE=SUBMIT VALUE="Make it so">
</FORM>
</BODY>
</HTML>
This page generates a form into which you enter the URL of your page
and specify the height and width of the browser. Clicking on the submit
button creates a browser window of the specified size. The new browser
window has all of the normal buttons and menu items associated with a browser
window. After the new window is created, the specified page is loaded into
it.
Protecting
your document from rogue users
This section explains how to write documents defensively. Readers will-sometimes
by accident, sometimes maliciously-try to do things with your document
that you did not intend them to do. You'd be surprised how many programmers
don't follow these principles. (Okay, you've seen enough bugs; maybe you
wouldn't be.)
Make Sure Your Functions
Are Loaded
First, you should make sure your functions are loaded, which is easy
to do. If you use a function that isn't loaded, your code will malfunction.
What's more, it's almost certain to malfunction in a manner that leaves
no doubt in the reader's mind that something went wrong-and that it's your
fault. If there are JavaScript expressions in the body of your page and
those expressions call other JavaScript functions that you wrote, place
those JavaScript functions in a <SCRIPT> element within the <HEAD>
element. The <HEAD> element is loaded before the <BODY> element;
you can depend on the function being there. This approach prevents a user
from impatiently clicking on a partially loaded page and invoking a JavaScript
function that hasn't been downloaded from the server yet.
Validate Input
If you're getting input from the reader, make sure you check it before
blindly using it, especially if it's supposed to be a number. Use the parseInt()
and parseFloat() functions. If it's supposed to be an integer, check it
like this:
if (Math.ceil(x) == x)
{
// it's an integer
}
else
{
// oops...
}
The Math object's ceil() method returns the next higher integer for
a floating-point value; for an integer value, it will return the same value.
The floor() method will also work.
Finally, if the number is supposed to be within a certain range of values,
make sure that it's within the specifications. For example, if it's supposed
to be a value from 1 to 10, put something like this in your code:
if (x < 1 || 1Ø < x)
{
alert("" + x + "is not between 1 and 1Ø");
return;
}
But Surely No One Would Do
That!
Sometimes users will input data that they're not supposed to. Some users
will be confused about what they're supposed to enter; they won't understand
what they're supposed to do. Other users will deliberately try to make
your page crash just for fun. Assume that when you ask for a number, someone
is going to enter anything except a number. "But you're not supposed
to do that" is not a valid defense for letting your code malfunction
just because you asked for a number but someone entered a phone number
or the word "no."
Not All Platforms
Are Created Equal, Part 2
There are some differences between the implementations of Netscape Navigator
for the various supported platforms. You can't expect everyone to use the
same platform that you use, and you should write your code to defend against
problems tied to specific platforms:
- Macintosh and Windows browsers can't return NaN (Not a Number) when
you call parseInt() or parseFloat() and the argument is not a number. They
return 0 instead.
- random() only works on UNIX platforms.
- Xwindow platforms have difficulty drawing new browser windows. Even
if you specify the parts of the window you want, you're going to get a
bare window.
- When you open a new document, call open() twice. Windows and Macintosh
browsers won't open the document unless you call open() twice.
Either use the navigator object's appVersion property to find out what
platform your JavaScript code is running on and adjust the runtime behavior
of your code accordingly, or include workarounds for known differences
between the platforms.
Document
maintenance
Nearly all Web pages are living documents. Someone has to maintain them,
and there's no guarantee that the person who wrote the original document
will always be around to explain how it works. For that matter, there's
no guarantee that the original author will remember how it works six months
later. Fortunately, there are several simple strategies for making your
documents easy to understand and maintain.
Comment, Comment, Comment
Use comments. For every function, explain what the parameters are and
what they're used for. Explain what the function does and what it does
if the inputs aren't entered correctly. Within the function body, explain
what each functional block does, how it does it, and why it does it. Some
people use a standard comment block for each function, like this:
//
// function name: (name of function)
// author: (author of function)
// revision history: (what was changed, when, and why?)
// parameters: (what are the parameters, what do they
// represent, what kind of values should they contain?)
// returns: (does the function return a value? What kind
// of value? What does the value mean?)
// purpose: (what does this function do?)
// global variables used: (useful in debugging to figure
// out who touched the contents)
//
Write down your assumptions. Do certain named objects have to exist
for the code to work? Say so!
Using comments to document your code helps you in two ways: First, it
helps indicate what you were thinking when you wrote the function. That
information will be invaluable later when you need to modify the function
or use it in another page.
Second, the act of documenting your code forces you to think about what
it does and how it does it. Often, you'll realize that there is a better,
faster, more reliable way to do what you're doing, and you'll improve your
code.
When modifying code, make sure that your comments are still accurate.
There is not much worse than comments that are no longer accurate and that
now lead you astray.
Consistent Internal Style
There are many ways to write JavaScript. The browser doesn't care what
the code looks like, as long as it can tell what you're doing. You need
to select a JavaScript style that works for you and that helps you visualize
what's going on. Although you have a lot of leeway, it's critical to be
consistent.
Here are some general pointers:
- Develop a consistent indentation style. I generally prefer to write
the start and end tags on separate lines, at the same level of indentation,
and I write the contents of the element at a greater indentation level.
I also write the start and end tags first, and then go back and insert
the contents. I avoid a lot of missing tag errors that way.
- Make it easy to differentiate different kinds of text. I prefer to
make tags and their attributes uppercase and variables lowercase. I prefer
function names made up of a verb followed by a noun, with the verb lowercase
and the noun with an initial capital letter (makeWindow, for example).
- Use short lines. If your code contains a mistake, Netscape will as
often as not tell you about it and it will display the number of the line
on which it found the problem. Long lines confuse Netscape, and it will
return the favor: Try to guess where the error in your code really is!
Also, long lines can be hard to follow; you'll be sorry that you didn't
break up your code when you still understood it.
The last
rule
The last rule is to have fun. JavaScript should make it fun to make
your pages more exciting and attractive. Don't make it drudgery!