Writing Your Own JavaScript Functions Part 2

By - thau!

Dealing with Y2K

Figure 6-9 works fine, but it has a little problem. Remember our discussion of the Y2K problem in the getYear() method of the Date object (“Writing the Date to Your Web Page” on page 26)? Different browsers deal with years differently. In some versions of Netscape, getYear() returns the year minus 1900. So if it's the year 2010, getYear() returns 110. Other versions return the full four-digit year if the year is before 1900 or after 1999. Different versions of Internet Explorer give different results for the same date as well.

The way to deal with this problem is to see whether the year returned by getYear()is less than 1000. If so, your visitor is using a browser that subtracts 1900 from the date if it's after 1899. In this case, you can get the correct four- digit year by adding 1900 to the date. you'll find a concise form for all this convoluted logic in the JavaScript function Y2K(), shown in Figure 6-11.


function Y2K(the_date)
{ if (the_date < 1000) {
the_date = the_date + 1900; } return the_date;
}

Figure 6-11: Dealing with the Y2K problem This function adds 1900 to the year if it is less than 1000. You can drop the Y2K() function into the script shown in Figure 6-8 to deal with its Y2K problem. Figure 6-12 demonstrates how the two look together.
<html>
<head>
<title>Date Printer</title>
<script type = "text/javascript">
<!-- hide me from older browsers
function getNiceDate(){
var now = new Date();
var the_month = now.getMonth()+1; 
// remember, January is month 0
var the_day = now.getDate();
X var the_year = now.getYear(); 
Y var the_fixed_year = Y2K(the_year); 
var the_nice_date = the_month + "/" + the_day + "/" + the_fixed_year;

return the_nice_date; } Z function Y2K(the_date)
{
if (the_date < 1000)
{
the_date = the_date + 1900; } return the_date;
}// show me -->
</script>
</head>
<body>Hello! Today is
<script type = "text/javascript">
<!-- hide me from older browsers
var today = getNiceDate();document.write(today);
// show me -->
</script>
</head>
</body>
</html>

Figure 6-12: The script in Figure 6-9 with the Y2K fix

Line-by-Line Analysis of Figure 6-12

Line X in Figure 6-12 uses the getYear() method to get the year, and Y calls the function Y2K() on the year to fix it up. The variable the_fixed_year is set to whatever Y2K() returns. The JavaScript in Figure 6-12 actually defines the function Y2K() after the getNiceDate() function. It might seem strange that getNiceDate() can call Y2K() even though Y2K() is defined after getNiceDate(). Remember, though, that when you define functions, you're just telling JavaScript their names and what they do, so the order in which you define your functions doesn't matter as long as you define them all before you call any of them from HTML.

Defining Variables Properly

The getNiceDate() function in Figure 6-12 calls the year variable the_year. However, when you look at how the Y2K() function appears in Z, you'll see that it calls whatever passes into it the_date. Since we're calling Y2K(the_year), JavaScript looks up the value of the_year and then sends that value to the Y2K() function. The Y2K() function stores that value in the variable the_date. In other words, the functions getNiceDate() and Y2K() have two different names for the same value. It's as if the functions are different countries where people speak different languages. If you try to talk about the_year inside the Y2K() function, it won't know what you're saying, and you'll get an error. Figure 6-13 shows you a graphical representation of how this works.
function getNiceDate()
{ var now = new Date(); var the_month = now.getMonth()+1; 
// remember, Jan is month 0 
var the_day = now.getDate(); 
var the_year = now.getYear(); 
var the_fixed_year = Y2K(the_year); 
var the_nice_date = the_month + "/" + the_day + "/" + the_fixed_year; 
return the_nice_date;
} function Y2K(the_date) {
if(the_date < 1000)
{
the_date = the_date + 1900;
}
return the_date;
}

Let's say now.getYear() returns 110, meaning that it's 2010 and your visitor is using IE. This means that the_year = 110 inside the getNiceDate() function. Why can't the Y2K() function access the variable the_year in getNiceDate()? Because when you first defined the_year, you put the word var in front of it:
var the_year = now.getYear();

The word var tells JavaScript to create the variable only for the function where it's defined. If you'd omitted var when defining the_year, you could access that variable inside the Y2K() function. You might think that freedom would be a good thing. Why shouldn't you access the_year anywhere in the program--why hide it inside getNiceDate()? The reason is that if you don't hide variables inside functions, you will soon drive yourself crazy. Having one function change a variable that was declared in another function is a major cause of difficult-to-debug problems. The idea of protecting variables declared inside functions is such an important programming concept that it gets its own name: encapsulation.

Consider the example in Figure 6-14 to see the headaches you'll avoid if you define your variables with var:


<html>
<head>
<title>Bad Encapsulation</title>
<script type = "text/javascript">
<!-- hide me from older browsers
function getNames()
{  the_name = prompt("What's your name?",""); 
dog_name = getDogName(); alert(the_name + " has a dog named " + dog_name);
}
function getDogName()
{ the_name = prompt("What's your dog's name?",""); 
return the_name;
}
// show me -->
</script>
</head>
<body>
<a href = "#" onClick = "getNames(); return false;">Click here for a survey</a>
</body>
</html>

Figure 6-14: The dangers of variables without var If I run this example and input thau when the prompt asks for a name and fido when the prompt asks for a dog's name, we end up with an alert that says fido has a dog named fido. Somewhere along the line, the program forgot that my name was thau and replaced it with fido.

This happened because both getNames() and getDogName() use a variable called the_name. Function getNames() saves the user's name in the variable the_name. Then function getDogName() saves the dog's name in the_name. If I had used var when declaring the variable the_name in the getDogName() function, JavaScript would have understood that the variable is specific to that function and would have left alone all the_name variables in other functions. Because I didn't use var when I set the variable the_name inside the getDogName() function, I unintentionally replaced the contents of the_name with the dog's name. When getDogName() exits and the alert comes up, we see the dog's name:


alert (the_name + " has a dog named " + dog_name);

If I had used var inside the getDogName() function, thau has a dog named fido would have come up. As your JavaScripts get longer, you're likely to use the same variable in different functions. Without var, it's very difficult to track down what's going wrong in these functions, so save yourself the headache with a little preparation.

Using var to hide variables inside functions also allows you to write functions that you can cut and paste into other scripts. If you define all your variables with var, you don't have to worry about whether a function you've written will mess up another function when you paste it into a different page. Otherwise you can't tell whether some variable in a program shares a variable name with your function.

Summary

There'san art to figuring out when to use a function and knowing the best way to write one. In general, the best time to use a function is for a simple task you need to execute more than once. For example, patching the Y2K bug in JavaScript is a task you may have to do repeatedly, so it's a good idea to create a function to handle it. As we see more complicated examples of JavaScript later in the book, you'll get a sense for what should go into functions. And, of course, as you view the source code on all the great web pages you see, you'll notice how various JavaScripters use functions.

Almost all complicated JavaScripts use at least one homemade function. In this chapter, you've seen how to write simple functions with no parameters and more complicated functions that take parameters and return values. If you found all of this a bit tricky, don't worry. you'll have many more opportunities to learn how to use functions in JavaScript.

Assignment

Write a page with three images on it, each of them a navigational icon leading to another website. Each time the user mouses over a navigational icon, it should do an image swap, and a new window should open with an appropriate URL. For example, the three images could be of an apple, a monkey, and a sun. (See http://www.bookofjavascript.com/Chapter06.) When the user mouses over the sun icon, the image could swap to a happy sun, and a window with the Sun Microsystems home page could open up. Create this effect using a function that takes three parameters: the image to swap, the new image to put in its place, and the URL to open in the new window. For example, if the user mouses over the sun icon, the image should look like this:
<img src = "normal_sun.gif" name = "sun" border = "0" 
onMouseOver = "fancySwap(window.document.sun,'hilight_sun.gif','http://www.sun.com/');" 
onMouseOut = "window.document.sun.src='normal_sun.gif';">

The first parameter in the function fancySwap() is the location of the image you want to swap. Notice that the image has the name sun. This means JavaScript will refer to this image as window.document.sun. The second parameter is the name of the GIF file to swap into the image called sun. The third parameter is the URL that should open in the new window. The function you write will start as follows:
function fancySwap(the_image_tag, the_new_image, the_url) {
you fill in here . . .
}

The lines of code you write will carry out the image swap (using what you learned in Chapter 4) and open a new window with the_url (using what you learned in Chapter 5).

NOTE As described in Chapter 5, if the user has a pop-up blocker, the code may not work.

Good luck--this is a tough one!

This article is excerpted from Chapter 6 of The Book of JavaScript with permission from No Starch Press




Page 2 of 2

Previous Page
1 2
 

Make a Comment

Loading Comments...

  • Web Development Newsletter Signup

    Invalid email
    You have successfuly registered to our newsletter.
  •  
  •  
  •  
Thanks for your registration, follow us on our social networks to keep up-to-date