Advanced Debugging Tools
Although it's possible to get a simple script working with an alert message or two, you might find some other tools useful as you build more complex scripts, and especially as you work with scripts that modify the DOM. The following are some useful debugging tools available for Firefox and Internet Explorer.
Web Developer Toolbar (Firefox)
The Web Developer Extension by Chris Pederick is an open-source extension for Firefox and other Mozilla-based browsers. This extension adds a toolbar to the browser with a variety of functions useful to developers. The following features are useful for JavaScript in particular:
Disable, JavaScript Disables JavaScript, useful for making sure pages function on non-JavaScript browsers. Information, Display ID and Class Details Displays the values of id and class attributes for all of the elements in a page; useful for attaching event handlers or CSS styles. Information, View JavaScript Displays all of the scripts that affect the current page, including those in external files. View Source, View Generated Source Displays the HTML source of the current page. Unlike the browser's regular View Source function, this displays the source after any scripts have acted upon it; useful for debugging scripts that modify the DOM.
Along with these functions, the toolbar includes many useful tools for debugging HTML and CSS, working with forms, and validating pages. To install it or for more information, see its official site at http://chrispederick.com/work/webdeveloper/.
Developer Toolbar (Internet Explorer)
Inspired by the Web Developer Extension for Firefox, Microsoft created a Developer Toolbar for Internet Explorer. Currently in beta, the toolbar works with Internet Explorer 6.0 or later. Here are some of its features useful for JavaScript programmers:
View DOM Allows you to browse the DOM of the current page and view details of elements, similar to Firefox's DOM Inspector. This feature is shown in Figure 16.3.
Disable, Script Disables JavaScript, enabling you to test how your site works without it. View, Class and ID Information Displays id and class attribute values; useful for attaching event handlers or CSS styles.
To download the IE Developer Toolbar, go to http://www.microsoft.com/downloads/ and search for "Developer Toolbar." The download is available for free and includes an easy installer.
DOM Inspector (Firefox)
The DOM Inspector is a tool built in to Firefox and other Mozilla-based browsers that enables you to browse the DOM of a web page and view the attributes of elements. You need to specifically select this feature at installation time, so you might need to reinstall Firefox to gain access to this feature. To see if your copy includes the DOM Inspector, open the Tools menu and check for a DOM Inspector menu item.
To use this tool, open the page you wish to inspect and then select Tools, DOM Inspector. You can then browse the DOM by clicking the [+] symbols for each section of the hierarchy. Select an item within the DOM tree to view its details in the right section of the window. The DOM Inspector is shown in Figure 16.4.
Viewing Generated Source
When your script modifies the DOM, the browser's View Source feature only gives you part of the pictureyou see the source of the page when it was loaded, rather than the source created by your script as it modified the page. To test scripts that modify the DOM, you can view the generated source as modified by the script.
In Firefox, this feature is built in: If you select part of a page, right-click, and select View Selection Source, you'll see the generated source. You can also use the Tools menu of the Web Developer Toolbar, discussed previously, to view the generated source.
For Internet Explorer, you can use a bookmarkleta short script stored as a browser bookmarkto view the generated source in a window. This bookmarklet is available at Jesse Ruderman's site at http://www.squarefree.com/bookmarklets/.
JavaScript Shell
Sometimes it's helpful to be able to simply type a few JavaScript commands to see what they do, either to narrow down a bug or simply to remember the syntax of a rarely used feature. The JavaScript Shell is a bookmarklet that opens a shell window that lets you type JavaScript commands and shows the results.
The shell opens in the context of the current document, so you can use it to explore the DOM of a page or to test scripts you're working on. This feature works only in Firefox, but an online version of the shell without the context feature works in Internet Explorer.
The JavaScript Shell is available from http://www.squarefree.com/bookmarklets/.
|
You should now have a good understanding of what can go wrong with JavaScript programs and the tools you have available to diagnose these problems. You can now try your hand at debugging a script.
Listing 16.2 shows a script I wrote to play the classic "Guess a Number" game. The script picks a number between 1 and 100 and then allows the user 10 guesses. If a guess is incorrect, it provides a hint as to whether the target number is higher or lower.
This is a relatively simple script with a twist: It includes at least one bug and doesn't work at all in its present form.
Listing 16.2. The Number-Guesser Script (Complete with Bugs)
1 <html>
2 <head>
3 <title>Guess a Number</title>
4 <script LANGUAGE="JavaScript" type="text/javascript">
5 var num = Math.random() * 100 + 1;
6 var tries = 0;
7 function Guess() {
8 var g = document.form1.guess1.value;
9 tries++;
10 status = "Tries: " + tries;
11 if (g < num)
12 document.form1.hint.value = "No, guess higher.";
13 if (g > num)
14 document.form1.hint.value = "No, guess lower.";
15 if (g == num) {
16 window.alert("Correct! You guessed it in " + tries + "
tries.");
17 location.reload();
18 }
19 if (tries == 10) {
20 window.alert("Sorry, time's up. The number was: " + num);
21 location.reload();
22 }
23 }
24 </script>
25 </head>
26 <body>
27 <h1>Guess a Number</h1>
28 <hr>
29 <p>I'm thinking of a number between 1 and 100. Try to guess
30 it in less than 10 tries.</p>
31 <form name="form1">
32 <input type="text" size="25" name="hint" value="Enter your
Guess.">
33 <br>
34 <b>Guess:</b>
35 <input type="text" name="guess1" size="5">
36 <input type="button" value="Guess" onClick="guess();">
37 </form>
38 </body>
39 </html>
|
Here's a summary of how this script should work:
The first line within the <script> section picks a random number and stores it in the num variable. The Guess() function is defined in the header of the document. This function is called each time the user enters a guess. Within the Guess() function, several if statements test the user's guess. If it is incorrect, a hint is displayed in the text box. If the guess is correct, the script displays an alert message to congratulate the user.
To test this program, load the HTML document into your browser. It appears to load correctly and does not immediately cause any errors. However, when you enter a guess and press the Guess button, a JavaScript error occurs.
According to the JavaScript console, the error message is this:
Line 36: guess is undefined
Internet Explorer's error message refers to the same line number:
Line 36, character 1: Object expected
As the error message indicates, there must be something wrong with the function call to the Guess() function in the event handler on line 36. The line in question looks like this:
<input type="button" value="Guess" onClick="guess();">
Upon further examination, you'll notice that the first two lines of the function are as follows (lines 7 and 8 of Listing 16.2):
function Guess() {
var guess = document.form1.guess1.value;
Although this might look correct at first glance, there's a problem here: guess() is lowercase in the event handler, whereas the function definition uses a capitalized Guess(). This is easy to fix. Simply change the function call in the event handler from guess() to Guess(). The corrected line will look like this:
<input type="button" value="Guess" onClick="Guess();">
Now that you've fixed the error, try the script again. This time it loads without an error, and you can enter a guess without an error. The hints about guessing higher or lower are even displayed correctly.
However, to truly test the script, you'll need to play the game all the way through. When you do, you'll discover that there's still another problem in the script: You can't win, no matter how hard you try.
After your 10 guesses are up, an alert message informs you that you've lost the game. Coincidentally, this alert message also tells you what's wrong with the script. Figure 16.5 shows how the browser window looks after a complete game, complete with this dialog box.
As you can see from the alert message, it's no wonder you didn't win: The random number the computer picked includes more than 10 decimal places, and you've been guessing integers. You could guess decimal numbers, but you'd need a whole lot more than 10 guesses, and the game would start to lose its simplicity and charm.
To fix this problem, look at the statement at the beginning of the script that generates the random number:
var num = Math.random() * 100 + 1;
This uses the Math.random() method, which results in a random number between 0 and 1. The number is then multiplied and incremented to result in a number between 1 and 100.
This statement does indeed produce a number between 1 and 100, but not an integer. To fix the problem, you can add the Math.floor() method to chop off the decimal portion of the number. Here's a corrected statement:
var num = Math.floor(Math.random() * 100) + 1;
To fix the script, make this change and then test it again. If you play a game or two, you'll find that it works just fine. Listing 16.3 shows the complete, debugged script.
Listing 16.3. The Complete, Debugged Number-Guesser Script
<html>
<head>
<title>Guess a Number</title>
<script LANGUAGE="JavaScript" type="text/javascript">
var num = Math.floor(Math.random() * 100) + 1;
var tries = 0;
function Guess() {
var g = document.form1.guess1.value;
tries++;
status = "Tries: " + tries;
if (g < num)
document.form1.hint.value = "No, guess higher.";
if (g > num)
document.form1.hint.value = "No, guess lower.";
if (g == num) {
window.alert("Correct! You guessed it in " + tries + " tries.");
location.reload();
}
if (tries == 10) {
window.alert("Sorry, time's up. The number was: " + num);
location.reload();
}
}
</script>
</head>
<body>
<h1>Guess a Number</h1>
<hr>
<p>I'm thinking of a number between 1 and 100. Try to guess
it in less than 10 tries.</p>
<form name="form1">
<input type="text" size="25" name="hint" value="Enter your Guess.">
<br>
<b>Guess:</b>
<input type="text" name="guess1" size="5">
<input type="button" value="Guess" onClick="Guess();">
</form>
</body>
</html>
|
Figure 16.6 shows the debugged example in action in Firefox after a successful game.
|
|
Main Menu
|