JavaScript Language Essentials | Page 6
[previous]
JavaScript Language Essentials
Using Do/While Loops
Sometimes you'll need to have a loop in your code that loops around a number of times, but there's no way of knowing how many times you'll want to loop. That's when you'll want to use a do/while
loop: you want to do
something, while
some value is true. Script 3.9 writes out each row of numbers as always, but this time it checks first to see if a number has been used already before putting it in a cell. If it has, the script generates a new random number and repeats the process until it finds one that's unique. Figure 3.6 shows the working, finally valid Bingo card.
Script 3.9. This script prevents numbers in a given column from being used more than once.
Figure 3.6 Finally, we've ended up with a valid Bingo card!
To use a do/while loop:
var newNum;
In the previous task, we initialized the newNum variable when we created it. Because we're going to be setting it multiple times, we're instead going to create it just the once, before we get into the loop.
do {
This line starts the do block of code. One of the things you have to remember about this type of loop is that the code inside the do block will always be executed at least once.
newNum = colBasis + getNewNum() + 1;
This line inside the loop sets the newNum variable to our desired number, as with previous examples.
}
The closing brace signals the end of the do block.
while (usedNums[newNum]);
The while check causes the do block of code to repeat until the check evaluates to false . In this case, we're checking newNum against the usedNums[] array, to see if newNum has already been used. If it has, control is passed back to the top of the do block and the whole process starts again. Eventually, we'll find a number that hasn't been used. When we do, we drop out of the loop, set the usedNums[] item to true, and write it out to the card, as in the last task.
|
Tip
- A common use for a
do/while loop would be to strip blanks or invalid characters off data entered by a user. But again, remember that the do block of code always gets executed, whether the while check evaluates to true or false.
|
Calling Scripts Multiple Ways
Up to this point in the book, you've seen scripts that usually run automatically when the page loads. But in the real world, you'll often want to give the user more control over your scripts, even allowing them to run a script whenever they want. In this example (Script 3.10), the script still runs when the page loads. But we also allow the user to click the link at the bottom of the page to rerun the script that generates the Bingo card entirely in their browser, without needing to reload the page from the server. This gives the user fast response with zero server load. This is the last of the Bingo card examples, wrapping up all the techniques we've used in this chapter to this point.
Script 3.10. Give your user the ability to run scripts themselves.
To call a script multiple ways:
window.onload = initAll;
In previous examples, we called newCard() when onload ran. Now, we're calling a new function, initAll() , which will handle all the required initialization steps.
function initAll() {
if (document.getElementById) {
document.getElementById ("reload").onclick = anotherCard;
newCard();
} else {
alert("Sorry, your browser doesn't support this script");
}
}
The initAll() function just gathers together several of the initialization steps we've previously seen, plus one new thing. If the browser is capable, all it does that's new (besides the object detection and the call to newCard() ) is set the link on the HTML page (the one with the id of reload ; refer back to Script 3.1) to call anotherCard() when it's clicked. The object detection was moved from newCard() to here as it's really part of the initialization routine, and that's what's handled by this function.
function anotherCard() {
for (var i=1; i<usedNums.length; i++) {
usedNums[i] = false;
}
newCard();
return false;
}
Here's the anotherCard() function that's called when someone clicks the link. It does three things:
- Sets all the items in the
usedNums[] array to false (so that we can reuse all the numbers again),
- Calls the
newCard() function (generating another card),
- Returns a value of false so that the browser won't try to load the page in the
href in the link (this was covered in Chapter 2).
|
Tip
- If you've gotten this far, you now know how to do something that many people consider to be a fundamental part of Ajax—using JavaScript to reload a part of a page instead of hitting the server and requesting an entirely new page. We'll be going into Ajax in much more detail in Chapters 15 and 16.
|
Using Multi-level Conditionals
There are times when you need more than two choices in a conditional test; then
and else
sometimes just aren't enough. While you can have nested levels of if
, it's often simpler to just use a switch/case
statement instead. The switch/case
construct allows you to check a variable against multiple values. As you can see in Figure 3.7, this script returns one of three different Presidential quotes as alert dialogs, depending on which button the user clicks. Script 3.11 shows the HTML, which is fairly simple. Script 3.12, the JavaScript, uses the switch/case
construct to differentiate between presidents.
Figure 3.7 Calling the function with each of the three buttons in the top window results in three different responses, as shown in the three dialog boxes.
Script 3.11. The HTML sets up the page for multi-level conditionals.
Script 3.12. This type of conditional allows you to check against multiple possibilities.
To use a switch/case statement:
window.onload = initAll;
When the page loads, call the initAll() function.
function initAll() {
for (var i=0; i
var thisElement = document.forms[0].elements[i];
if (thisElement.type == "button") {
thisElement.onclick = saySomething;
}
}
}
In the function, we loop through all the fields in the form on the page. For each field, the loop looks at the type of field. If it's a button, then we add an onclick handler to call the saySomething() function.
function saySomething() {
This begins the saySomething() function.
switch(this.value) {
The value of the this object is used as the parameter to switch() . Its value will decide which of the below case statements gets executed.
case "Lincoln":
alert("Four score and seven years ago...");
break;
If the value of the this object is "Lincoln", this alert appears. Regarding break , if the user clicked Lincoln, we're in this section of code. However, we've done everything we want to do, and so we want to get out of the switch . In order to do that, we need to break out. Otherwise, we'll execute all of the code below, too. While that continued execution can be handy in certain circumstances, this isn't one of them.
case "Kennedy":
alert("Ask not what your country can do for you...");
break;
If the user clicked Kennedy, we end up in this case block.
case "Nixon":
alert("I am not a crook!");
break;
And finally, if the user clicked Nixon, we end up here, popping up another alert and then breaking out of the switch .
default:
If you were wondering what would happen if the user's entry didn't meet one of the above criteria, you're in the right place. The default section is where we end up if our switch value didn't match any of the case values. The default block is optional, but it's always good coding practice to include it, just in case (so to speak). In this script, there's no code here to execute, because we shouldn't ever get here.
}
This closing brace ends the switch statement.
|
Tip
- A
switch statement can be passed other values besides strings. You can use it with a numeric value or even have it evaluate a mathematical result. If its result should be numeric, though, be sure that the case statements match—your case statements need to be checking for numbers, not strings (e.g., 5, not "5").
|
Handling Errors
While you may have years of experience working with computers, it's a good bet that many of your site's visitors won't. Consequently, you'll want to give them meaningful error messages instead of the technobabble that most browsers return if they object to something the user does. Script 3.13 shows how to use JavaScript's try/throw/catch
commands to produce a friendly, useful error message. We've built this into a simple square root calculator.
Script 3.13. Use this script to have JavaScript handle errors gracefully.
To handle errors gracefully:
var ans = prompt("Enter a number", "");
Here's an ordinary, everyday prompt, which we're storing in the ans variable for later use. In this case, we want the user to enter a number. If they do that successfully, JavaScript displays the square root of whatever they entered.
try {
However, if they didn't enter a number, as in Figure 3.8, we want to be able to catch it gracefully and display something meaningful. Yes, we'll be polite about it, even though the user entered words when the alert asked for a number. We start off by using the try command. Inside its block of code, we'll check to see if the user's entry was valid.
Figure 3.8 We want a number, but the user could enter anything, like this non-numeric entry.
if (!ans || isNaN(ans) || ans
throw new Error("Not a valid number");
}
There are three things we care about: no entry at all, or if the user entered something but it was non-numeric, or if the entry was numeric but was a negative number (because the square root of a negative number is an imaginary number, and that's beyond this example). If !ans is true, that means that the user didn't enter anything. The built-in isNaN() method checks to see if the parameter it's passed is "Not a Number." If isNaN() returns true, we know that something invalid was entered. And if ans is less than 0, it's a negative number. In any of these cases, we want to throw an error; in this case, it says "Not a valid number". Once an error is thrown, JavaScript jumps out of the try block and looks for a corresponding catch statement. Everything between here and there is skipped over.
alert("The square root of " + ans + " is " + Math.sqrt(ans));
If something valid was entered, the square root is displayed, as shown in Figure 3.9.
Figure 3.9 Here's the result of the script acting on a number.
}
This closing brace ends the try block.
- catch (errMsg) {
alert(errMsg.message);
}
Here's the promised and looked-for catch statement. The error is passed in as a parameter, and the message part of the error is displayed (Figure 3.10). If no error was thrown, the code inside the catch will never be executed.
|
Figure 3.10 If bad data was entered, let the user know.
Tip
- There's another, optional part to this: the final
{} block. That would go after the catch and would contain code that should be executed whether the try threw an error or not.
|
[previous]
URL: