CHAPTER SEVEN: JavaScript for Client-Side Content Behavior

Chapter opener image: © Godruma/ShutterStock

Overview and Objectives

We began our exploration of JavaScript in the previous chapter with a primary focus on client-side computation and data validation. If calculations can be done with JavaScript on the client side (in the browser), and the results presented immediately to the user, this avoids having to send the data to a server and then bring the results back for display. Also, data validation with JavaScript on the client side is one way to help prevent potentially malicious data from being sent to a web server.

In this chapter, we will look at another aspect of JavaScript usage. JavaScript can also help you improve the functionality as well as the appearance of your web pages. In particular, we will enhance our home page by dynamically adjusting its content with a rotating sequence of business-related images, and also with dropdown menu options. In fact, the dropdown menu feature will persist as we navigate to other pages on our website.

In this chapter we will discuss the following:

  • How to create a rotating sequence of images (often called a “slide show”), along with the associated JavaScript

  • How to use an onload event attribute for the body element, whose value will be a JavaScript function that activates our slide show when our home page loads

  • How to create a JavaScript array of images for our rotating display

  • How to use the JavaScript switch-statement for decision making when we decide what sequence of images to display, based on the day of the week

  • How to use the JavaScript for-loop for repetition when we actually rotate our images

  • How to create a dynamic dropdown menu, along with the associated CSS and JavaScript

  • How to use the onmouseover and onmouseout event attributes, whose values will be JavaScript functions that cause a dropdown menu to appear or disappear

  • How to use the new HTML5 pattern attribute to perform validation of form input data without resorting to JavaScript, and the required, attribute to ensure that input that is actually required is not omitted

  • How to use the onchange attribute to provide immediate user notification when a checkbox is clicked

  • How to provide a Body Mass Index (BMI) report to the user via a new web page that is “persistent”, rather than a popup window that has to be “dismissed” before returning to the browser

Recall that in neither of the previous two chapters did we have a complete version of our Nature’s Source website. However, in this chapter we will again have two versions of this sample site. The first version, found in the nature1 subdirectory, contains only enough files to display a revised home page and demonstrate both of the new features discussed in this chapter: the “slide show” of rotating images and the dropdown menus. In this version, none of the links on the home page are active.

In the second version, found in the nature2 subdirectory, the home page is the same as in the first version, except that now all links on the home page are active. Most of these just take you to pages with minimal content that you have seen in previous versions of the site. However, we also have two important links that provide the features we discussed in the previous two chapters: one that takes a user to the BMI calculator and a second that goes to our feedback form. In fact, because our menu bar with its dropdown menu options appears on all pages in nature2, all links are available on all pages.

Recall as well that with nature3 of Chapter 3, and nature2, nature3, and nature4 of Chapter 4, SSI was used for access to the “common” markup for each page of the given website. This will also be true for both nature1 and nature2 in this chapter. So, to view either site properly you must either go to the book’s website, or set up your own SSI-aware server to serve your own copy of the website. The latter choice is preferable, of course, since that will allow you to experiment and do the exercises more easily.

7.1 Enhancing Our Website with a Home Page “Slide Show” of Rotating Images and Dropdown Menu Options on Every Page

Let’s begin with a look at FIGURE 7.1, which shows a display of the home page for our sample Nature’s Source website in this chapter (either the nature1 version or the nature2 version).

When compared with the last similar version of our home page (as seen in Figure 4.29, for example), the only visible difference you see (aside from a different image) is the list of dropdown menu1 options under the Products+Services menu item. However, there are actually two major enhancements in this version: in addition to the dropdown menus (also under Your Health, About Us, and Contact Us), the image now shown in the figure is just one of a sequence of six images that continually rotate as long as the page is displayed. In fact, there are two different groups of six images, one that displays during “weekdays” (Monday to Thursday) and shows indoor scenes, and the other that displays during “weekend days” (Friday to Sunday) and shows outdoor scenes. This chapter discusses the new JavaScript and CSS features that enable these enhancements.

FIGURE 7.1 graphics/ch07/nature1/displayIndexHtml.jpg

A Firefox browser display of ch07/nature1/index.html (or ch07/nature2/index.html), both of which illustrate rotating images and dropdown menus. Photo: © coloroftime/iStockphoto

The HyperText Markup Language (HTML) file producing the display in FIGURE 7.1 is ch07/nature1/index.html, shown in FIGURE 7.2. The only difference between this file and ch07/nature2/index.html is the comment in line 2. Note, first of all, the following features of the markup in this file and the files it includes, some of which we will need to discuss at length as we proceed:

  1. As another version of our index.html document, it continues to make use of four external HTML files included via SSI (lines 1, 5, and 6 and 31 of Figure 7.2).

  2. The included file document_head.html (shown in FIGURE 7.3) now contains two new script elements (lines 11 and 12) for access to the rotate.js and menus.js scripts to handle the image rotation and the dropdown menus. The script in rotate.js (FIGURE 7.5) will handle the rotating images, and the script in menus.js (FIGURE 7.7) will handle the dropdown menus. Note that we retain links to both of our CSS files, desktop.css and tablet.css, so both versions of the website in this chapter can still be viewed in either “desktop view” or “tablet view”.

  3. The included file menus.html (shown in FIGURE 7.4) has been revised to accommodate the new dropdown menu feature that we discuss in detail later in this chapter, along with the new menu-related CSS shown in FIGURE 7.6.

  4. We have introduced the onload event attribute (line 3 of Figure 7.2) to start our image rotation once the body of our home page has fully loaded.

  5. We have revised the img element on our index page (lines 25–27 of Figure 7.2) to handle the sequence of rotating images, rather than a single static image.

FIGURE 7.2 ch07/nature1/index.html

The index file showing the HTML markup for the home page of our Nature’s Source website with rotating images and dropdown menus.

FIGURE 7.3 ch07/nature1/common/document_head.html

The common document head file for all pages on the Nature’s Source website. The nature1 website has only one page, but an identical file is used for the complete nature2 website as well.

7.2 Implementing Our “Slide Show” of Rotating Images

The replacement of a static image on our home page with a “slide show” that consists of a continuous, cyclic display of a sequence of various images related to our business might be regarded in some quarters as somewhat frivolous. On the other hand, it might also help to grab and keep a visitor’s attention. It is worth keeping in mind that choosing how much activity to have on your home page (or any page) is both a key design decision and a bit of a balancing act. You can either attract and keep visitors or cause them to quickly abandon your site, depending on how much and what kind of dynamic activity they encounter when they first come to visit.

The general idea of our “slide show” is this. When the script in rotate.js of Figure 7.5 is run after the index.html page is loaded, the first thing that happens is a determination of the current date. An appropriate collection of images is then assembled, depending on whether it’s a weekday or a weekend. Then those images are displayed one after the other, with repetition when the end of the sequence is reached, until the user closes the page or clicks on a link to another page.

For this purpose, we have assembled, in the subdirectory images of the nature1 directory (as well as the nature2 subdirectory), two sets of images, one set showing indoor exercises and the other showing outdoor exercises. The images of outdoor exercises are named outdoor1.jpg to outdoor6.jpg. These outdoor images will be displayed on a weekend (Friday to Sunday). On the other hand, the images of indoor exercises will be displayed on weekdays. These image files are named indoor1.jpg to indoor6.jpg.

FIGURE 7.4 ch07/nature1/common/menus.html

The included HTML file containing the markup for our menu and its dropdown menu items.

FIGURE 7.5 ch07/nature1/scripts/rotate.js

The JavaScript code for handling the rotating images on the home pages of this chapter’s nature1 and nature2 websites.

FIGURE 7.6 ch07/nature1/css/desktop.css (excerpt)

A portion of the “desktop” CSS style file for this chapter, showing the styles for both the always-visible “high-level” main menu headers and the dropdown submenu options.

FIGURE 7.7 ch07/nature1/scripts/menus.js

The JavaScript show( ) and hide( ) functions for the dropdown menu options in our nature1 and nature2 websites.

To understand how the slide show works, you need to examine both the index.html file of Figure 7.2, which contains the onload attribute and the revised img element, and the rotate.js script shown in Figure 7.5.

7.2.1 The onload Attribute of the body Element: Starting the Slide Show after the Home Page Loads

In line 3 of Figure 7.2 we see the following HTML markup for the opening tag of the body element:

body onload="startRotation( )"

The onload attribute of the body tag is another event attribute whose value should be whatever action is to be taken once the page with the given body has fully loaded. This action is often, as in this case, simply a function call, but it could also be several JavaScript statements, separated by semicolons. In this case, the JavaScript function being called is startRotation( ), which has been defined as part of the script in rotate.js, and it begins the image rotation that now features prominently on our home page. We will discuss this function shortly.

7.2.2 The Revised img Element for the Slide Show

Look a little more closely at the img element in the index file of Figure 7.2, which is shown in lines 25–27:

<img id="placeholder" src=""
   alt="Healthy Lifestyle"
   width="256px" height="256px">

This img tag now has an id attribute with the value "placeholder", suggesting (correctly) that the img element is to “hold the place” for each successive image to be inserted into the image location during the rotation. Also, the value of the src attribute starts off as the empty string, but the script will change this value to the name of each successive image file as the rotation proceeds.

The value of the alt attribute is "Healthy Lifestyle", a term that may reasonably be applied to all of our images, so it does not have to be changed.

The width and height attributes have fixed values that are the same, so we have a square image. Recall that for the sake of efficiency all of the images we display should ideally have the same size to eliminate the need for any resizing effort by the browser (or any distortion in the image if the actual dimensions give a different aspect ratio). The aspect ratio of an image is defined as the ratio of its width to its height.

7.2.3 The rotate.js Script

In what follows, we use our discussion of the rotate.js script to introduce (or examine further) the following JavaScript topics:

  • The Date object

  • The switch-statement

  • Creating a new array and “populating” it with values

  • The for-loop

The JavaScript Date Object: Getting the Day of the Week

The first of the new JavaScript features we encounter in the rotate.js file shown in Figure 7.5 is the JavaScript Date data type. The executable part of the script begins in line 5 by creating a new Date object (with the Date( ) method call) and storing it in a variable called today:

var today = new Date( );

TABLE 7.1 Methods of the Date object in JavaScript.

Method Return Value
Date( ) (the default constructor method has an empty parameter list) A Date object containing all relevant information for today’s date and time
getDate( ) day of the month (1–31)
getDay( ) day of the week (0–6) (0 is Sunday)
getFullYear( ) year (a four-digit number)
getHours( ) hour (0–23)
getMilliseconds( ) milliseconds (0–999)
getMinutes( ) minutes (0–59)
getMonth( ) month (0–11)
getSeconds( ) seconds (0–59)

A method call of this type is usually referred to as a constructor method, or just a constructor, since it “constructs” a new object of type Date. Those familiar with other languages such as C++ or Java will already be familiar with this terminology and syntax. We gave the variable this name because by default such a Date object contains all the information we might need to know that pertains to today’s (i.e., the current) date.

There are many pieces of information we might want to know about today, or any other day, and an equal number of methods that we can call on the Date object referred to by the today variable to get that information. TABLE 7.1 shows some of those methods. See the References section at the end of this chapter for more information.

The particular method we will need is getDay( ), which returns a value of 5, 6, or 0 if today is Friday, Saturday, or Sunday (respectively), or a value of 1 to 4 if today is a day from Monday to Thursday, inclusive.

The JavaScript switch-statement for Decision Making: Choosing Which Group of Images to Rotate

We have already seen how the JavaScript if..else-statement can be used to choose between two alternatives, or between two or more alternatives if we choose to use a “nested” if..else construct. We could use such a construct in our current situation again, but sometimes it is more convenient to use another kind of statement when we need to choose one alternative from among many (one day from seven possible days of the week in our current context, for example).

The JavaScript switch-statement is another form of conditional statement that is found in many other languages as well, including C, C++, and Java, and which allows us to make this kind of choice.

Here is the general format of the switch-statement:

switch (expression)
{
   case value_1:
      statements;
      break;
   case value_2:
      statements;
      break;
      ...
   case value_n:
      statements;
      break;
   default:
      statements;
      break;
}

The execution of a switch-statement proceeds as follows. First, the expression in the parentheses following the keyword switch is evaluated. This value is then checked against the value in the first case (value_1 above). If a match is obtained, the statement(s) following this case are executed and the switch-statement terminates because the break; statement at the end of this case will cause execution to “break out” of the switch and carry on with the statement immediately following the switch-statement.

If the value of expression does not match the value in the first case, the search continues with each of the subsequent case values (also called case labels) in turn. Any match farther along the way will result in behavior analogous to that we described when we had a match for the first case. The values of a case label may be an integer, a character, or even a string, but all case labels should be of the same value type, and expression should evaluate to a value of that common type.

Each group of case statements in a switch-statement is almost always terminated by a break; statement to exit the switch, once the statements for that case have been executed. Sometimes, however, programmers will omit the break; in one or more cases to create a “drop through” effect. For example, if you delete the break; statement before the second case, and if the value of our expression matched value_1, the statements in both the first and second case will be executed. In fact, we see one form of this usage in the switch-statement in our rotate.js.

If no case value is matched by the value of expression, the statements after default: will be executed. While it is not necessary to include the default: option as the last part of a switch statement, it is a good programming practice to always include it. Also, the break; statement at the end of the default: option is not strictly necessary, since the switch-statement ends at that point in any case.

Now look at how we use the switch-statement in rotate.js (see lines 9–19 in Figure 7.5). In order to handle the images for our slide show properly, the first thing we need to do is decide which group of images to use, the indoor ones or the outdoor ones. As we know, this depends on the day of the week.

We begin by setting a variable called prefix (the prefix to which a number will be added to get an actual file name) to an appropriate initial value. Since every file is located in the subdirectory images, we initialize this variable with the string "images/" (line 9 of the rotate.js script in Figure 7.5):

var prefix = "images/";

Next, depending on the day of the week, we want to append either "indoor" or "outdoor" to the value in the variable prefix. This is where we use a switch-statement in which the expression to be evaluated is today.getDay( ) (lines 10–19 of the rotate.js script in Figure 7.5):

switch (today.getDay( ))
{
   case 0:
   case 5:
   case 6:
      prefix += "outdoor";
      break;
   default:
      prefix += "indoor";
}

The return value of the method call today.getDay( ) will be an integer in the range from 0 to 6. If it is either 0, 5, or 6 we have a weekend day, since these values correspond to Sunday, Friday, and Saturday, respectively. In these cases we want to append the string "outdoor" to our variable prefix so that the value of prefix becomes the string "images/outdoor". On the other hand, if the value returned is 1, 2, 3, or 4 we have a weekday, and the value of prefix becomes "images/indoor".

Note the use of the “special assignment operator” += to add either "outdoor" or "indoor" to the original value of prefix. Most operators in JavaScript can be extended in this way using the assignment operator. In our case, the statement

prefix += "outdoor";

has exactly the same effect as this statement:

prefix = prefix + "outdoor";

We have also chosen to not use a break; for the first two cases, allowing for the fall-through effect discussed earlier. In fact, those first two cases do not even have statements of their own in this particular switch-statement.

In this switch-statement we are using our default: option to deal with the remaining days of the week, and we will append the string "indoor" to our variable prefix in that case. Other alternatives to this code will be explored in the end-of-chapter exercises.

Creating Our Own JavaScript Array: Creating Storage for Our Image Filenames

In the previous chapter we had a very brief encounter with a built-in JavaScript array that was useful when accessing certain Document Object Model (DOM) elements. Here our goal is to have an easy way to access a sequence of image files, and the JavaScript array turns out to be the most convenient way to do that, since arrays are generally used to store lists of values of any kind. In our case, therefore, we will store a list of the filenames of the images that will be displayed in our slide show.

Now, however, we have to create our own array. We do this by first declaring a variable called imageArray to hold a reference to an array object and then we call the constructor method of the Array data type with the operator new in much the same way as we did earlier when we created a Date object. This statement occurs in line 22 of the rotate.js script shown in Figure 7.5:

imageArray = new Array(6);

The constructor, as always, performs the necessary operations to set up our array. A significant difference this time around is that we provide the value 6 as a parameter to the constructor, which specifies that we want the array to have a size of six (be able to hold six values, i.e., six image filenames). The net effect is as though we now have six variables, named imageArray[0], imageArray[1], imageArray[2], imageArray[3], imageArray[4], and imageArray[5]. Note again that arrays in JavaScript (your own as well as any that are built-in) are zero-based; that is, index numbering starts at 0. These are the components or elements of the array. Thus the array gives us an easy way to handle several, or even a very large number, of variables of the same kind. In fact, we can easily automate the processing of all the array elements with the help of another JavaScript control statement, the for-loop, which we discuss next.

The JavaScript for-loop for Repetition: Storing the Image Filenames in Our Array

A JavaScript script will often require that one or more actions be repeated. For example, to build our array of images, we have to repeat the act of inserting the name of an image file into that array six times. Most C-based programming languages, including JavaScript, have three different kinds of loop control statements to handle repetition: the for-loop, the while-loop, and the do..while-loop. Because it is the most convenient choice for our immediate purpose, we examine the for-loop more closely here, and discuss the other two in the end-of-chapter exercises.

Here is the general format of a for-loop:

for (initialization; condition; update)
{
   statements;
}

The keyword for is followed by a required pair of parentheses containing three semicolon-separated parts: initialization; condition; update. The statement(s) in the braces are called the body of the for-loop. If there is only a single statement in the body, the braces are optional.

This is how we execute a for-loop. The initialization is performed (once) before the loop begins. Then, if condition is true, we execute the body. Next, update is performed and condition is re-checked. As long as condition remains true, we continue to re-execute the loop body and perform update, in that order. When a check of condition finds it to be false, the loop terminates and script execution continues with the first statement following the for-loop.

Of course, most of the time we want the loop to terminate eventually, so we must ensure that update eventually causes condition to become false.

Once we have set up the “infrastructure” for our image array—the imageArray variable itself, and the correct prefix for our image filenames that will go into that array—we can populate the array with the required filenames with a simple for-loop (lines 23–24 of rotate.js in Figure 7.5):

for (i=0; i<imageArray.length; i++)
    imageArray[i] = prefix + (i+1) + ".jpg";

The execution of this for-loop proceeds as follows:

  • The initialization sets the variable i to 0.

  • The condition (i<imageArray.length) is then checked. Any JavaScript Array object has a length property that is accessed using the same dot-notation syntax that is used to access an object method. This condition uses that length property, which in this case has the value 6, and since the value of i is currently 0, the condition is true.

  • Since the condition was true, we now execute the (single-statement) body of the for-loop. This statement creates the proper filename for the first image and inserts it into the array. The proper filename is created by appending the prefix variable with the value of (i+1), and then adding the string for the file extension, which is ".jpg". Note that we need i+1 here to avoid the classic “off-by-one” error, because i has started at 0, but the names of the image files start their numbering at 1. If the current day is a weekday (for example), the value of prefix to which we are adding this information will be "images/indoor", so that imageArray[0] will be assigned the value "images/indoor1.jpg".

  • We execute the update statement, i++, which increments i to 1.

  • We check the variable i to see if it is still less than 6, which it is, so the condition is still true.

  • We therefore continue by executing the loop body again, which, this time around, assigns the value "images/indoor2.jpg" to imageArray[1].

  • This process continues until we have set the final value of our array, imageArray[5], to be "images/indoor6.jpg".

  • The following execution of the update statement, i++, sets i to 6, which is no longer less than imageArray.length.

  • At this point the loop terminates, and imageArray contains the names of all six image files.

Rotating Our Images: The rotate( ) and startRotation( ) Functions

We have now completed the setup of the array data structure that contains the “slides” (images) for our “slide show”, and we are ready to define the functions that actually perform the slide show (the image rotation). It is important to note that the remainder of the script rotate.js in Figure 7.5 is in fact just setting up the functions to perform the slide show, but the show does not start as this script executes. It only starts when the page has loaded. This is a difference worth remembering.

To display our images we define two functions, one called rotate( ), which performs the rotations, and a second one called startRotation( ), which initializes the first image and then calls rotate( ) to continue with the rotation. Recall that it is the startRotation( )function that was the value of the onload attribute in our index.html page. We could have used the rotate( ) function directly as the value of the onload attribute, but depending on the speed at which things are happening, a user might see the value of the alt attribute in the image location briefly before the rotation got under way. By using the separate function startRotation( ) to initialize the first image directly, and then start the rotation, we hope to avoid this possibility.

We should preface our detailed discussion by noting our use of the global variable imageCounter to keep track of the image we are working with at any given time, and we initialize this variable to 0 (line 27 of Figure 7.5). Global variables are variables declared outside any function, but accessible from within the body of any function. They are very convenient, but also “dangerous” to use, since they can be altered from anywhere in your JavaScript code, and it is therefore easy to alter them inadvertently by mistake, leading to hard-to-find bugs in your code. Use them sparingly and very carefully, if you must use them at all. Our only excuse here is that our script is very short and the variable is only being accessed in one place and we would not want to put it inside our function since then it would be set to 0 each time our function was called, instead of being incremented each time, which is what we need.

The function rotate( ) (lines 28–34 of Figure 7.5) performs the actual image rotation. Each time it is called, it first creates a variable called imageObject and assigns it a reference to the DOM img element on our home page. Recall from the discussion of index.html that the img element had an id attribute with a value of 'placeholder', so we get this reference with a call to the getElementById( ) method. (Note that we are using single quotes here, but only as a not-so-subtle reminder that we can.) Once we have this reference to the img element object, we can access the src attribute of the img element with the usual dot-notation syntax (imageObject.src) and assign to it the filename of the current image from our array of images (imageArray[imageCounter]). The browser then takes care of updating the home page display with that image.

Before leaving the rotate( ) function, we must increment the imageCounter variable so that the next time rotate( ) is called the next image in the sequence will be displayed. And finally, note that when imageCounter reaches 6 we have to set it back to 0, for two reasons: first, to get our “rotational” effect, and second, to prevent our array index from quickly getting out of bounds and trying to access images that don’t exist.

Now that we know what rotate( ) does when called, the only remaining question is this: When, exactly, is it called? And that’s the job of the startRotation( ) function, so let’s look at it.

The startRotation( ) function does two things. First, it chooses an initial image for display, before rotate( ) is called to begin the rotation, for reasons we explained above. We opt to display the last image in the sequence first, as this initial image, so that the first image seen as the rotation begins appears in its proper place in the rotation.

The second and last action of startRotation( ) is to call the setInterval( ) function. This is a built-in JavaScript function that takes two parameters. The first parameter is a string containing an action to be performed (often a function call, as in this case), and the second parameter is the length, in milliseconds, of a time interval. A call to setInterval( ) with these two input values causes the action to occur after each time interval of the given length. Thus the call made by our startRotation( ) (namely, setInterval('rotate( )', 2000)) causes our rotate( ) function to be called every 2 seconds (2000 milliseconds). This, in turn, causes the image on our home page to change every 2 seconds.

7.3 Implementing Our Dropdown Menus

In this section, we discuss the details of the second major new feature of our sample website in this chapter, the dropdown menu options. We are again dealing with the “stripped down” first version of the site found in the nature1 subdirectory. In this version, none of the links on our home page are active, but the dropdown feature is fully functional in all cases, which is all we need for our discussion. Section 7.4 discusses the more complete nature2 version of our site, in which all the links are active and lead to other pages, but there is no functionality to be seen there that we have not seen before, except for the enhancements to our BMI and feedback forms, which we also discuss in section 7.4.

To follow the discussion in this section, you will need to refer to four different files from this chapter:

7.3.1 An Overview of How Our Dropdown Menus Work

Let’s begin with a brief overview of how our dropdown menus work, and start by examining the HTML markup structure that gives us those menus. This markup is in menus.html, shown in Figure 7.4, and as you can see by looking at line 6 of index.html in Figure 7.2, menus.html is included, via SSI, right after the logo on our home page.

Perhaps the first thing we should point out is that our “dropdown” menus don’t really “drop down” in the literal sense, so this can be confusing. In fact, they are always sitting there, just where you see them when they are “dropped down”, but they are “invisible” most of the time. When a user hovers the mouse over a menu bar with a hidden “dropdown” menu, the “dropdown” does not “drop down”; it simple “appears” (becomes visible).

So, now to continue our discussion. The menu that sits below the logo on our home page now consists of two kinds of menu options, that is, two kinds of links to other pages. The first kind of “high level” option is illustrated by the seven options that show up on the menu when the page is displayed. Not all of these options are “created equal”, since some (but not all) of them have dropdown suboptions. So, the second kind of menu option link is illustrated by the dropdown list of suboptions that appears (“drops down”) when the mouse is placed over an option of the first kind, if that option actually has the dropdown feature. This only happens for the third to the sixth options on this menu (Products+Services, Your Health, About Us, Contact Us). The first two menu options (Home, e-store) and the last (Site Map) do not have any dropdown suboptions.

Figure 7.4 shows that the entire main menu “strip” on our home page is enclosed in a new HTML5 semantic nav element. Within this nav element is an unordered list containing seven list elements corresponding to the seven high-level menu options on our menu. Finally, under each of these menu options that has a dropdown submenu (the third to the sixth) there is a div element containing a number of anchor elements corresponding to the number of dropdown options for that particular submenu. As you can see from the markup, three of the submenus contain four options (lines 9–12, 18–21, and 27–30), and the remaining one contains two options (lines 36–37).

Note that, for simplicity, we have followed the standard approach of making the hyperlinks “defunct” by using a value of '#' for their href values, which simply means that the links will not actually take us anywhere. This is what we mean by saying that the links on this page are “inactive”. We will have more to say about these links in section 7.5 when we compare the menus.html markup for nature1 with the corresponding markup for nature2.

7.3.2 The onmouseover and onmouseout Attributes: Showing and Hiding Dropdown Menu Options

Continuing our examination of Figure 7.4, we note the appearance of two new event attributes: onmouseover (lines 4, 5, 7, 8, 16, 17, 25, 26, 34, 35, and 40) and onmouseout (line 2). Each onmouseover attribute appears as the attribute of a list element containing one of the seven “high-level” menu options, or as the attribute of a div element containing a group of dropdown options.

Because the value of each onmouseover attribute is a call to the show( ) function, when the mouse pointer is placed over any of the main menu options, a call to show( ) is made. Depending on which menu option the mouse pointer is over, that call is one of show('m1'), show('m2'), show('m3'), show('m4'), show('m5'), show('m6'), or show('m7'). The parameter is the id value of the corresponding div element containing the associated dropdown submenu option group. However, you will note that there are only four groups of submenu options. In fact, there is no div with an id of m1 or m2 or m7, so the call to show( ) in any one of these cases has no effect since there is no submenu to drop down. We could explain this by saying we are “future proofing” our code: If we ever do add submenu divs with these id values, they will drop down automatically without further code modification.

The purpose of a function call like show('m3') (for example) is to make visible the drop-down menu contained within the div element whose id is m3, which is the one under the menu item Products+Services. We shall look at the details of this function later in this chapter. As long as the mouse pointer is over the main menu option or the dropdown menu underneath it, that dropdown menu will remain visible.

The onmouseout attribute of the outermost nav element (line 2) has as its value a call to the function hide( ). The purpose of hide( ) is to make invisible any currently showing dropdown menu, which it does when the mouse pointer moves away from the nav element, that is, away from all of the “high-level” menu options and their dropdown submenus.

7.3.3 The CSS for Our Dropdown Menus

Much of the CSS for our home page in this chapter we have already discussed in Chapter 4. However, our dropdown menu setup makes use of some CSS features that we have not discussed previously, so we introduce them here. For purposes of the discussion, we include, in Figure 7.6, only the relevant portion of the current chapter’s desktop.css file, in which we see, of course, some familiar CSS along with the new features.

Here are the things to note about the CSS shown in Figure 7.6:

  • We use a single class called Links, combined with various descendant selectors, to style both the “high-level” menu options, which are always visible in the menu bar, and the dropdown submenu options, which only appear when the mouse pointer hovers over one of the “high-level” menu options that actually has a dropdown submenu. Comments indicate which styles apply to which menu options.

  • The .Links li style in lines 42–50 removes the markers from list elements and floats them left, setting up a horizontal main menu, just as we had in Chapter 4.

  • The style .Links li:last-child makes use of the :last-child pseudo-class to style the last li element (the last item in the menu bar) a little bit differently than the others (a slightly different width and no right border). When applied to an element, the :last-child pseudo-class identifies the last element of that type that is a direct child of its parent (in this case, the last li element that is a child of the ul parent element).

  • In the style for .Links li a in lines 58–65 you see something you have not seen before: the style rule display: block. An a element is by default an inline element, but turning these anchors (links) into block elements allows us to give them a width, padding, and margins, something we cannot easily do with inline elements.

  • The style .Links li a:hover in lines 67–70 provides a different background color for the menu links as well as the submenu links, when the mouse pointer is hovering over those links.

  • The .Links div style in lines 73–77 contains three items of interest. First is the style rule position: absolute, which takes the menu strip out of the “normal flow” of the page and, in this case, allows the following blocks to rise up under the menu and close up the space that would otherwise be there to accommodate the dropdown submenus when they are activated. Second is the border: 1px solid #048018 “shorthand” style rule, which gives us a 1-pixel, solid green border all around our dropdown submenu options. And finally, the visibility property is set to hidden to hide the submenu options when the page is first displayed.

  • The .Links div a style in lines 79–87 styles the anchors (links) in our dropdown menus. The key thing to note here once again is the display: block style rule. As before, this allows us to give them all a uniform width. But this is needed here for an even more important reason. Normally an a element is inline, and without this rule the submenus would appear in a horizontal row across the page, instead of one under the other as we would like.

You may have to read through the above list several times while referring to Figure 7.6. An even better approach is to view the nature1/index.html file in a browser while you have the nature1/css/desktop.css file open in an editor. Then you can comment out or alter each style rule in some other way as that rule is mentioned, and then refresh the browser display to see the effect of your actions. There is no better way to learn quickly the real effects or purpose of a particular CSS style. One of the end-of-chapter exercises guides you through a number of such activities.

7.3.4 The JavaScript for Our Dropdown Menus: The show( ) and hide( ) Functions

Finally, we are now ready to look at the JavaScript code that causes the visibility state of the menu suboptions to alternate between visible and hidden. This code is found in the file menus.js, which is shown in Figure 7.7. It is a much-simplified version of the code from http://javascript-array.com/.

This short script contains, once again, two global variables. One of these is called isShowing and the other is called dropdownMenu. The rest of the script consists of two short function definitions. One function is called show( ) and the other hide( ). The names of the variables and the functions have been chosen to suggest their purpose, always a good programming practice.

When this script is run, the global variable isShowing is initialized to false to indicate that none of the submenu options is showing, and the dropdownMenu global variable is initialized to null to indicate that no dropdown submenu has yet been chosen. Remember that these global variables are accessible from any part of the script and therefore, in particular, from each of the two functions.

If you now look again at the menus.html file in Figure 7.4, you can see that the show( ) function is called when the user places the mouse over one of the “high-level” menu items in the menu bar, and at that point the show( ) function is also passed the id value of the div of the corresponding submenu, as discussed earlier. This passed value will be one of 'm1', 'm2', 'm3', 'm4', 'm5', 'm6', or 'm7', corresponding to the position of the menu item in the menu bar, although (as we pointed out earlier) there are currently no dropdown menus corresponding to either 'm1' or 'm2' or 'm7'.

The first action of the show( ) function is to hide any submenu that may be currently displayed by calling the hide( ) function. It then retrieves the DOM element whose id value it has been passed by calling the getElementById( ) method and passing along the same id that it received. The visibility property of that DOM element is then given the value visible and the global variable isShowing is set to true to indicate that this menu item now indeed “is showing”.

The function hide( ) is even simpler. It checks to see if any DOM element is visible by looking at the variable isShowing, and if there is such a visible DOM element, it is made invisible by setting its visibility property to a value of hidden.

7.4 Notes on the nature2 Version of Our Nature’s Source Website

We pointed out at the beginning of the chapter that the nature1 version of our website in this chapter had no active links, since we were using it solely for demonstrating our slide show and drop-down menus. The nature2 version, on the other hand, is the most complete version of our site to date.

First, the home page looks the same as the home page for the nature1 version, except that all links are now active, so the nature2 directory includes an HTML document file to be displayed whenever the user clicks on any of the now-active links. With two exceptions, these pages contain essentially the same content as they did in Chapter 4, except that all pages have been modified to show the same main menu and footer (but not the rotating images) of the home page. The two exceptions are the Compute Your BMI dropdown submenu option found under the “high-level” menu option Your Health, and the Feedback Form dropdown submenu option found under the “high-level” Contact Us menu option. These two links bring up the latest versions of our BMI and feedback forms, and we will say more about them in a moment.

The contents of the images and scripts subdirectories are the same for both nature1 and nature2. The desktop.css and tablet.css style files for nature2 contain the full contents of those files for nature1, plus a few additional styles to help with the styling of the newly revised BMI calculator form and feedback form pages.

It would be useful at this point for you to make yourself thoroughly familiar with this up-to-date version of our sample site before we enhance it further with server-side processing using PHP in the next chapter. However, just before you do that, let’s take a moment to mention a few enhancements that we have applied to our two forms, which also invite some experimentation on your part.

7.4.1 What’s New in Our BMI Form?

Recall from the previous chapter that when a user successfully completed a BMI form and clicked the Compute your BMI button, the resulting report was presented in a JavaScript popup window, and that window had to be dismissed before the user could return to using the browser.

The report returned upon completion of the BMI form in nature2 of this chapter contains the same information as before, but is presented in a new web page, which therefore does not have to be dismissed before continuing to work in the browser. FIGURE 7.8 shows the result when the user has asked for a detailed report, and FIGURE 7.9 shows the relevant modified code from nature2/scripts/bmiCalculate.js that does the job.

FIGURE 7.8 graphics/ch07/nature2/displayBMIReport.jpg

A Firefox browser display of the BMI report produced as a separate web page instead of a JavaScript popup.

FIGURE 7.9 ch07/nature2/scripts/bmiCalculate.js (excerpt)

The JavaScript code segment that displays a BMI report as a new web page.

In this version of the script we call the window.open( ) JavaScript method (line 70 of Figure 7.9) rather than the alert( ) method. For our usage of the method we supply three parameters. The first parameter is the URL of the page to load. Since we are not loading any page, but instead just writing our report to an empty window, we supply an empty string for this value. The empty string for the second parameter is the default value and indicates that we want a brand new window (as opposed to replacing the contents of the current window, for example). The third parameter is the most interesting one. It too is a string, and contains a comma separated list of values. More values are possible, but we have used only four: the width and height of the new window, and the distance of the top left corner of our new window from the top and left sides of the browser window. All measurements are in pixels.

The other new feature of our BMI form is illustrated by the display in FIGURE 7.10. What is different this time around is that this popup message appears the moment the user clicks on the checkbox to request an email report. In other words, the user is spared the frustration of clicking on the check box, typing in an email address and then being told that email is not yet implemented. In fact, if you look closely you can see that the textbox where the email would be typed actually contains a similar message, so the user should not be clicking the checkbox in any case! As you can see in line 60 of FIGURE 7.11, this message shows up because it’s the string assigned to the value attribute of that textbox, and in fact no email address can be entered because we have given this textbox the readonly attribute (see line 61 of Figure 7.11).

FIGURE 7.10 graphics/ch07/nature2/displayBMInoEmail.jpg

A Firefox browser display showing the popup message that appears when the user clicks on the checkbox that requests the BMI report to be sent by email.

Implementing this latest feature requires some new markup, as well as some new JavaScript. The new markup is shown in Figure 7.11, and the new JavaScript in FIGURE 7.12. In Figure 7.11 we show the complete fieldset element containing the markup for dealing with email, so that we can see the context of the changes.

FIGURE 7.11 ch07/nature2/pages/bmiForm.html (excerpt)

The HTML markup for the revised fieldset element of the BMI form that handles the user’s request for a BMI report via email.

FIGURE 7.12 ch07/nature2/scripts/bmiFormValidate.js (excerpt)

The JavaScript function that handles the event that occurs when the user clicks on the checkbox that requests a BMI report via email.

Note that the input element with "type=checkbox" also has a new event attribute, namely onchange="handleBMIEmailRequest( )", and we can see the definition of this function in Figure 7.12. When called, this function displays the popup message window that we see in Figure 7.10, and then makes sure the checkbox is unchecked. So, when is the function called? It’s called the moment there is any “change” in the status of the corresponding input element, in other words the moment the user tries to get an emailed BMI report by clicking on the checkbox.

7.4.2 What’s New in Our Feedback Form?

Although in the previous chapter we mentioned the new HTML5 pattern attribute and how it could help with form data validation, we did not use it at that time since our focus then was on validating form data with JavaScript. In this chapter’s version of our feedback form, we remedy that omission by using the pattern attribute to validate first name, last name, email address, and phone number. We have already discussed the regular expressions involved, and you can see how these are used as values of the pattern attribute by studying the excerpt from the current feedback form markup shown in FIGURE 7.13 (lines 27, 33, 40–41, and 48). Note from that figure that we have given all of our input elements with type="text" the required attribute as well (lines 27, 33, 42, and 48). Thus we have implemented a “double whammy” in terms of validation: the required attribute insists that something go into the textbox, and the regular expression in the pattern attribute value insists that it be the “right thing”. Although the textbox for the feedback subject does not have a pattern attribute, it must not be left empty.

FIGURE 7.13 ch07/nature2/pages/feedbackForm.html (excerpt)

The HTML markup from the current version of our feedback form showing how we use a pattern attribute with a regular expression for its value to help us validate our form data, and also the use of the required attribute.

FIGURE 7.14 graphics/ch07/nature2/displayEmptyFeedbackFormHtml.jpg

A Firefox browser display showing that all the empty input elements that have a required attribute are outlined in red, with an HTML5 generated request to fill in the first one. This occurs when we try to submit a completely empty form.

The effects of these changes can be seen in FIGURES 7.14 and 7.15. In Figure 7.14 we have clicked on the Send Feedback button when the form is empty. The result is that all the textboxes created by the input elements in our markup are outlined in red, indicating that they need to be filled in, and there is a popup message to that effect pointing at the first of those textboxes. All this has been achieved simply by giving each input element a required attribute. Compare that with what would be needed to achieve the same thing with JavaScript!

FIGURE 7.15 graphics/ch07/nature2/displayErrorFeedbackFormHtml.jpg

A Firefox browser display showing a feedback form that is correctly filled out except that the first name does not begin with a capital letter.

In Figure 7.15 all the required information has been entered and we have again clicked on the Send Feedback button. This time there is a problem with the first name, since our regular expression (line 27 of Figure 7.13) requires that it start with a capital letter. Thus the textbox is again outlined in red and, though it is not shown in the figure, if you hover your cursor over the textbox you will see the advisory popup message given as the value of the title attribute of that input element (see line 26 of Figure 7.13):

"Initial capital, then lowercase and no spaces"

Our use of the pattern and required attributes in our HTML markup in feedbackForm.html means that we have a much simpler version of the file feedbackFormValidate.js (see FIGURE 7.16), which now contains only two short functions. The first is feedbackFormValidate( ). Once all the input data has been validated, this function simply displays a message saying everything is OK in a new browser window, much like our revised BMI report was presented in the revised version of our BMI form discussed above.

FIGURE 7.16 ch07/nature2/scripts/feedbackFormValidate.js

The limited JavaScript code now needed for our feedback form validation, which is much less than we used previously because we are now using the pattern attribute.

The second function is handleFeedbackEmailRequest( ). The user’s request for an email response in this form is handled somewhat differently from the way it was handled in the BMI form. In this case, the user is actually allowed to enter an email address because even though email itself is not yet implemented, we still want to validate it with our regular expression, and the user is so advised by a popup message when the checkbox is checked.

7.4.3 What’s Different about the nature2 Markup for Our Menu Bar?

One more difference we should point out concerns the markup for our menu bar in nature2, as compared with the analogous markup for nature1. In nature1, none of the links were active, which meant that we could, and did, simply give all links (main menu options as well as dropdown menu options) the href="#" attribute.

However, in nature2 some of the “options” on the main menu bar are actually live options, and some are not. In particular, Home, e-store, and Site Map are “actual” links, but Products+Services, Your Health, About Us, and Contact Us are not. In these last four cases, only the dropdown options under each heading are active links.

What this means is that, since these last four headings on our menu bar are no longer links, they have to be marked up and styled differently. As you can see in FIGURE 7.17, each of the first, second, and last main menu options (lines 4, 5, and 41) is still an a element within a li element, but the third to sixth main menu options (lines 8, 17, 26, and 35) are now just span elements. The best way to “experience” the difference is to compare what happens when you hover your mouse over Products+Services (for example) in nature1 and then in nature2. The CSS for these span elements is not shown in the text, but for the sake of completeness you should check desktop.css to see how they are styled, and also compare the two versions of menus.html shown in Figures 7.4 and 7.17.

Summary

In this chapter you have seen how JavaScript can be used to provide a simple “slide show” of rotating images on our home page, and, in conjunction with CSS styles, to create a drop-down menu of options for navigating around our website that appears on every page of the website.

In the case of the rotating images, you saw how the value of the onload event attribute of the body element of a page could be set to a JavaScript function that is invoked when the page is fully loaded. In our case, this arrangement caused a sequence of images to be displayed in a rotational order that repeated until the page was closed.

In the case of the dropdown menus, you saw how the values of the onmouseover and onmouseout event attributes of an element can be set to JavaScript functions that are triggered to execute and either show or hide menu options, depending on whether the user’s mouse is hovering over an element or has moved away from it. The new CSS concepts we found useful in this context were the display, visibility, and position properties.

In the course of these discussions we also learned more about some basic JavaScript features, including the Date and Array data types, the switch-statement, the for-loop, and the set-Interval( ) function.

We also updated our BMI and feedback forms with some enhancements. The results from submitting these forms were displayed in a new web page, thus eliminating the alert( ) popups. Much of the JavaScript validation was replaced by use of the new HTML5 pattern attribute, and we also made good use of the required and readonly attributes for input elements, as well as the onchange event attribute. Finally, we used the built-in JavaScript window.open( ) method to display to the user the reports from our BMI and feedback forms in a new browser window.

FIGURE 7.17 ch07/nature2/common/menus.html

The markup for the menus in the nature2 version of our website. Note the difference in the markup for the main menu bar items that have a dropdown submenu (lines 8, 17, 26, 35), as compared to the markup for those same menu items in the nature1 version of the same file, shown in Figure 7.4.

Quick Questions to Test Your Basic Knowledge

  1. We have not actually used the term dynamic HTML document, but what do you suppose we would mean by that term if we did use it?

  2. What kinds of values can be used for the case labels in a JavaScript switch-statement?

  3. What is the name of the element attribute whose value you would set if you wanted something to happen when a web page is fully loaded, and what kind of value would it have?

  4. What is the name of the element attribute whose value you would set if you wanted something to happen when the user moved the mouse over that element?

  5. What is the name of the element attribute whose value you would set if you wanted something to happen when the user moved the mouse away from that element?

  6. How do you put text in a textbox (instructions for the user, let’s say) but prevent the user from editing that text?

  7. How do you prevent a user from submitting a form with an empty textbox if you really wanted the user to put something into that textbox?

  8. What would you do if you wanted to make sure that, before submitting a form, the user actually entered a six-digit integer into a particular textbox?

  9. What event attribute would you use if you wanted to notify the user of something the moment that use clicked on a checkbox?

  10. What is the usual symbol used as the value of the href attribute of an a element if you do not want the link to go anywhere?

  11. Why did we change the markup on some of the menu options (but not others) for our main menu bar in going from the nature1 website to the nature2 website in this chapter?

  12. What JavaScript function would you use if you wanted a function you had written to be called every five seconds and what would that function call look like if your function was called doIt( )?

  13. What is the JavaScript statement that would create an array called a of size 10?

  14. Our “dropdown menus” don’t actually “drop down”. Explain this statement.

  15. What is the output of the following JavaScript code segment? And note that the answer depends on the day you are answering this question!

var today = new Date( );
document.write(today.getDay( ));

Short Exercises to Improve Your Basic Understanding

  1. The switch-statement that we used in our rotate.js script is certainly not the only way, and you could argue that it’s not even the best way, to write this particular switch-statement. It does the job, but instead of using the default: option to handle the weekday cases, it might make the code a little clearer if we had one group of explicit cases to handle the weekend days (which we do), another group of explicit cases to handle the weekday cases (which we don’t), and use the default: option for something that is extremely unlikely to happen, such as displaying for the user a message via the alert( ) function to inform the user that something has gone wrong. Revise rotate.js to implement the switch-statement in this way, and test to make sure the revision works.

  2. Revise the script in rotate.js so that the images are shown in random order, rather than always repeating the sequence in the same order, and test to make sure the revision works.

  3. The generic switch-statement discussed in this chapter is equivalent to the following generic nested if-statement:

    if (expression == value_1)
    {
         statements;
    }
    else if (expression == value_2)
    {
         statements;
    }
    ...
    else if (expression == value_n)
    {
         statements;
    }
    else
    {
         statements;
    }
    

    Revise rotate.js by replacing its switch-statement with an equivalent nested if-statement of the above form, and test it to make sure it works.

  4. The switch-statement in rotate.js can also be replaced by the following if.. else-statement:

    if (today.getDay( )==0 || today.getDay( )==5 ||
        today.getDay( )==6)
      prefix += "outdoor";
    else
      prefix += "indoor";
    

    Revise rotate.js by replacing its switch-statement with an equivalent if..else-statement of the above form, and test it to make sure it works. This exercise and the previous one should be a reminder that even for very short and simple code, it’s often worthwhile to stop and think about the “best” way to write the code, rather than going with the first thing that comes to mind.

  5. JavaScript provides two other loops in addition to the for-loop: the while-loop and the do..while-loop. Though you can use whatever loop you like in most situations, the kind of loop you actually choose in a particular situation will often depend on the logic, since some loops can be more “readable” than others in certain cases.

    Here, in generic form, are those other two loops:

    initialization;         initialization;
    while (condition)       do
    {                       {
       statements;             statements;
    }                       }
                            while (condition);
    

    The major difference between these two loops is that the body of the do..while-loop is guaranteed to execute at least once, since the condition is not checked until that has happened. The body of the while-loop, on the other hand, may never execute, since the check of the condition is made at the beginning.

    In order for the body of either loop to execute properly, the initialization must be done correctly, and for either loop to terminate properly the body must contain an action that eventually causes condition to become false. In the case of the for-loop, the initialization and update are handled by the loop structure itself. In the other two loops, it is the programmer’s responsibility to ensure that proper initialization and updating are performed.

    As a simple example, here is a version of each of the three loops that adds the positive integers from 1 to 10, inclusive:

    var sum = 0;                 var sum = 0;          var sum = 0;
    var i;                       var i = 0;            var i = 0;
    for (i=1; i<=10; i++)        while (i < 10)        do
    {                            {                     {
       sum += i;                     ++i;                  ++i;
    }                                sum += i;             sum += i;
                                 }                     }
    

    We used the for-loop in this chapter to build our array of images. A for-loop was the appropriate choice in that case, because we knew exactly how many times we wanted the loop to execute (the number of images we had), and this is the kind of scenario for which the for-loop is well suited. However, either of the other loops could have been used.

    Revise rotate.js, first of all, to replace the for-loop with an equivalent while-loop to build the image array. Then revise it a second time to use an equivalent do..while-loop. In each case, test to make sure everything still works.

  6. In our rotate.js script we defined two separate functions, rotate( ) and start-Rotation( ), to handle the slide show. We can also perform our image rotation with a single rotate( ) function if we implement it somewhat differently, making it a recursive function, which is a somewhat advanced concept. Here is that implementation:

    var i = 0;
    function rotate( )
    {
      document.getElementById('placeholder').src=imageArray[i];
      i++;
      if(i >= imageArray.length) i = 0;
      setTimeout('rotate( )', 2000);
    }
    

    In this version of the image rotation, we begin by initializing the variable i to 0. This variable will again keep track of the subscript (or index) of the array element that provides the filename of the current image. This time around the function rotate( ) itself must be the value of the onload attribute of the body element in index.html and performs the image rotation starting when the page has loaded by proceeding as follows.

    As before, we access the img tag as a DOM element by using the id ('placeholder') of the tag, and set its src attribute to the filename given by imageArray[i]. This makes sure that the image given by imageArray[i] is displayed in the web page.

    We then increment i to prepare for loading the next image in the sequence when the time comes and, as before, we have to make sure the value “wraps to 0” when the time comes. Finally, we have to answer this question: When does the time come to load the next image? And this is where the major departure from the way we previously did things takes place. The last statement in our rotate( ) function is

    setTimeout('rotate( )', 2000);
    

    which essentially says, “Wait 2000 milliseconds (2 seconds) and then call yourself again.” Students coming from C, C++, or Java will immediately recognize this as a recursive function call (a function calling itself), but even they may be bothered by the fact that the function will continue to call itself forever. That is, there is no “stopping condition” for the function. But this is a case where that is not a major concern, since we do in fact want the images to keep rotating for as long as the user is viewing the page, which may be a long time. If the user displays our page and then goes home for the night, the images should still be rotating the next morning. Of course, if the user closes our page, or browses to another site, the function (and everything else associated with our page) goes away.

    So, revise the rotating-image feature of the website to incorporate this recursive version of the rotation function.

  7. One of the files our markup file nature1/index.html links to is the CSS style file nature1/css/desktop.css, and the part of this file dedicated to styling our menus is seen in Figure 7.6.

    Make the following changes and perform the suggested actions to observe the changes in the display of nature1/index.html when you do so. This will give you a good sense of which style rules are affecting which parts of the display.

    1. Comment out the “mini-reset” style rule at the beginning of desktop.css (lines 7–10, not shown in Figure 7.6) that sets all margins and padding to 0, and then reload to see what effect, if any, this has had.

    2. There are a number of different colors, specified with hex values, in the CSS shown in Figure 7.6. Change each of these values, one at a time, to red. First predict what the effect will be, then reload the page to check your prediction.

    3. Comment out the float: left style in line 43.

    4. Comment out the list-style: none style in line 49.

    5. Comment out the display: block style in line 59.

    6. Comment out the width: 127px style in line 44.

    7. Comment out the visibility: hidden style in line 76.

    8. Comment out the width: 124px style in line 81.

Exercises on the Parallel Project

The website for your business has now developed to the point where it has information about the business itself and some more detailed information about its products and/or services, as well as some data-validated forms for placing an order and for gathering feedback from your users. Now it’s time to improve the “look and feel” of your site by adding some additional “rotating” images and some dropdown menus. Once again, of course, this “parallels” the look and feel of our own Nature’s Source sample website.

  1. Find some more images relating to your business that you can legally copy and use on your website (at least six, let’s say) and replicate for your site the rotating image feature illustrated by our own example when you display the home page of either the nature1 website or the nature2 website of this chapter.

  2. Create a version of your website that “parallels” our nature1 example of this chapter. That is, your site must have only a home page, but it must also have the rotating images and dropdown menus analogous to what you see in Figure 7.1 of the text. Or, if you wish, give it a fancier dropdown menu. The one in the text can be regarded as a “minimal” dropdown menu whose functionality you should be able to replicate using the text code as a model and making appropriate changes for your particular situation. On the other hand, there are lots of dropdown menu options “out there” on the Internet, and you may find one more to your liking. If you do, and it’s not illegal to do so, go ahead and use it instead. The menu options and suboptions will, of course, depend on the nature of your business, but most of them should be the same or similar to those in the text example.

    In this part of these exercises, none of the menu options on either the main menu bar or the dropdown submenus should be active. In other words, your resulting website should “parallel” our nature1 example, in which none of the links are active.

  3. Make a copy of your website from exercise 2 above, and revise it so that all menu links become active and the same header with menu bar and associated dropdown menu options appear on all pages. The rotating images are to appear only on your home page, since you don’t want to distract the user from the serious business of buying your products once that user has started to browse your site. The appearance of the business logo and menu bar on all pages helps to give your visitors a feeling of consistency in the “look and feel” of your site as they browse from page to page. In any case, your result this time should “parallel” our nature2 example, in which all of the links are active on all pages.

  4. A final (optional, unless your instructor requires it or some variation of it) exercise: In this version of your website, you may also wish to implement some of the form enhancements we discussed in section 7.4, and you may do that as well.

  5. And, of course, everything should validate as HTML5 and CSS3.

What Else You May Want or Need to Know

  1. A significant difference between arrays in JavaScript and arrays in more “conventional” languages such as C, C++, and Java is that in JavaScript the size of an array is not fixed once the array is created. You can change the size of an array at any time. You can even assign a variable to an array location with a subscript that is beyond the current last element of the array. For example, if we only have a six-element array of images to begin with, we could nevertheless say

    imageArray[20] = "pawan.jpg";
    

    and the length of the array will be extended to 21 (remember that indices start at 0). That you can do this is not necessarily a good thing, and there are good reasons why those other languages won’t let you do it, even though you may find it convenient from time to time.

  2. You should be aware, particularly if you plan to do any extensive JavaScript programming for your website, that there are many sources for JavaScript code on the web, and it is always a good idea to avoid “reinventing the wheel” if at all possible. First of all, if you see a site that exhibits some behavior that you admire and would like to use on your own site, that behavior may be produced by JavaScript and the code may (or may not, remember) be freely available for use by others. In the (reasonably frequent) cases where the code is available, often all the writer will ask is that acknowledgment be placed in the code wherever you use it. Also, there are many JavaScript code libraries (or “frameworks”) that are also freely available and contain a great deal of ready-made functionality that you may find useful when designing your site. Many of these were listed in the References section of the previous chapter.

References

  • 1. The W3Schools JavaScript tutorial start page is located here:

    http://www.w3schools.com/js/default.asp
    
  • 2. The W3Schools JavaScript reference site, which contains lots of examples on both JavaScript itself and the HTML DOM, can be found here:

    http://www.w3schools.com/jsref/default.asp
    
  • 3. In particular, for further information on the JavaScript Date and Array data types, see:

    http://www.w3schools.com/jsref/jsref_obj_date.asp
    http://www.w3schools.com/jsref/jsref_obj_array.asp
    
  • 4. Here is another site you may find helpful when investigating JavaScript features:

    http://www.javascriptkit.com/jsref/
    
  • 5. The following page contains a table showing many JavaScript frameworks and their features:

    http://en.wikipedia.org/wiki/Comparison_of_JavaScript_framework
    
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.86.134