Intro Page (Flash)

Cookie Setting Function

Overview: This function has been inserted in the index.html (intro) page to set a session cookie for the current web page domain with the details of the visitor's favourite pans to be used in the wish list or for storing the text resizing preference.

The function SetCookie(), with two parameters, is inserted into the head of the page. The parameters for the function are: the name of the cookie to be set and the data string to be stored in the cookie. The value of the cookie data string (value) is escaped inside the function prior to storing it in the cookie so that it may contain any characters desired. This is necessary as certain characters (spaces, commas, etc) have special meanings in the construction of cookies. If the cookie value is retrieved later, the cookie data value will have to be unescaped before being used. The cookie set, because the function does not include any instructions to the contrary, will only be good for the current browser session and will be accessible to all pages on the current domain.

The function SetCookie():

// function to update/create a new session cookie for 
// the current domain, where the name of the cookie 
// is 'name' and the data stored in the cookie is in 
// the 'value'
function SetCookie(name, value) {
	// set the cookie with escaped value.
	document.cookie = name + "=" + escape(value);
}
	

Defining the initial 'wishlist' cookie value:

	
// define the cookie contents for the wishlist
var cookieString = 'copperfry:20 inch copper pan=prodblank&' + 
	'greenfry:20 inch green pan=prodblank&' + 
	'silverfry:20 inch silver pan with cover=product1&' +
	'redfry:20 inch red pan=prodblank';	 
	

Calling SetCookie() on page load:

<body onload="SetCookie('wishlist',cookieString);">
	

In the body of the page a call is made to set a session cookie called 'wishlist' (the first parameter in the SetCookie() function call) with value of copperfry:20 inch copper pan=prodblank&greenfry:20 inch green pan=prodblank&silverfry:20 inch silver pan=product1&redfry:20 inch red pan with cover=prodblank (the second parameter). This data string is stored in a previously declared variable named "cookieString" found also in the head of the page. The call to set the cookie is made whenever the page has finished loading completely using an onload event handler in the body element. This particular cookie is to be retrieved on the 'wishlist.html' page and used to display a list of items and their pictures that the customer has previously asked to be added to a wish list.

Cookie debugging code:

if (document.cookie) {
	document.write("The following cookie string is available " + 
		" for this page: " + 
		unescape(document.cookie));
} else {
	document.write("There either are no cookies or the " + 
		"cookie was just set. " + 
		"Try reloading the page to see cookies.");
}
	

Related to this function is some code to display the contents of all cookies available for the web site to be used for debugging purposes. It's located on the main page (main.html). In the above, it first checks to see if the document.cookie exists and has some kind of content (any content). If it does, then it displays the unescaped contents of the document.cookie string. Otherwise, it tells you that the cookie is missing or was just set. This particular functionality would not be included in the end site.

Credits/Modifications: The SetCookie() function is based on code from http://www.nicksScripts.open.ac/cookie.html but the script found there does not escape the cookie value which I added to handle all cookie values safely. Without this change some values would be illegal and not stored correctly or possibly at all. The remaining code was written by me, based on general information from Study Guides 7 and 8.

The flashSeen Cookie

Overview:The index.html page also includes code to create a flashSeen cookie that is used to determine whether a user has already seen the flash movie page. If so, the page is skipped and the user directly relocated to the main page.

The setPersCookie() function:

This function sets a persistent cookie so that it can be determined whether the index page has been previously visited.

//create a function to create a persistent cookie that records whether the 
//user has visited the flash screen before
function setPersCookie(name, value){
	//create an expiry date six months hence
	expireDate = new Date;
	expireDate.setMonth(expireDate.getMonth()+6);
	//set the cookie
	document.cookie = name + "=" + escape(value) + ";expires=" + expireDate.toGMTString();
}
	

The function takes two parameters to determine the name of the cookie and its value. A new date object is created to hold the expiration date of the cookie (persistent cookies require an expiration date to be set as a GMT string). The setMonth() method of the date object is used to set the expiration date to 6 months hence.

The document.cookie property is then used to set the cookie, using escape() to deal with any special charaters and toGMTString() to convert the date into the required format.

On the index.html page

The setPersCookie() is called on the unload event for the page to set a cookie named flashSeen to the value 'true' when a user unloads the page.

<body onunload="javascript:setPersCookie('flashSeen','true');">
<!-- Set a flashseen cookie to true on unload -->
	

Within the body of the document, the function cookieValue() is used to determine the value of the flashSeen cookie, if this value is 'true' (ie the page has already been seen), then an if block is used to automatically re-direct the user.

The cookieValue() function:

This function takes a string as a parameter. It initially splits the cookie string held based on ';'. This seperates out each multiple cookie into an array thisCookie. A for loop then splits each element of this array based on '=' and tests each element at [0] ie. the cookie name, against the string provided as the parameter. If their is a match, then the element at [1] is returned ie. the corresponding cookie value.

If no name matches a 0 is returned.

//create a function to return a cookie value given a cookie name
function cookieVal(cookieName){
  thisCookie = document.cookie.split("; ")
  for (i=0; i<thisCookie.length; i++) {
    if (cookieName == thisCookie[i].split("=")[0]) {
      return thisCookie[i].split("=")[1]
    }
  }
  return 0
}
	

Otherwise, on first visit the value is not 'true' and the index page loads normally allowing the user to view the movie.

The setFlashToFalse() function:

A second function is defined that 'manually' sets the flashSeen cookie to false.

function setFlashToFalse(){
 setPersCookie('flashSeen', 'false')
}
	

This is to enable the flash movie to be seen if the user clicks the intro link from any of the pages from within the site by overrriding the automatic re-direct. It is therefore called when the user clicks the intro link

<a href="index.html" onmouseover="chgImage('intro', 'introHov')"
  onmouseout="chgImage('intro', 'introNorm')" onclick="javascript:setFlashToFalse()">
 <img src="images/intro.gif" alt="Intro link" width="152" height="24" 
  border="0" name="intro" id="intro">
</a>
	

Credits/Modifications:The setPersCookie() function is based on the setCookie() function defined in script 12.1 in Chapter 12, Javascript 5th Edition, Negrino and Smith. This function however takes two parameters allowing the cookie name and value to be specified.

The cookieValue() function is taken directly from the cookieVal() function defined in script 12.4, Javascript 5th Edition, Negrino and Smith.

The setFlashToFalse() function is an elaboration of the the setPersCookie() function used to set a particular cookie to a particular value by nesting functions.

Return to top


All Pages

Rollover Menus (Including external js file)

The External Javascript file

Overview:The main page (main.html) is linked to an external javascript file (external.js), as in fact are all the main site pages. The purpose of this file is to define the javascript necessary to add dynamic content to the previously static left side navigation links.

This involves switching one image for another when the user hovers their mouse over the link, and then returning to the original image when the mouse moves elswhere on screen.

Since all site pages include these links, it is sensible to precipitate the common code out to a seperate external file, and link this file to all relevant pages. This improves both scalability and maintainability.

Create the variables:

In order to improve response times, all images are loaded into the browser cache on first visit. A set of variables must be created to hold the images

//store images in the cache if the browser understands the image object
if (document.images){//create  variables to hold the images in the cache
  introNorm = new Image; 
	introHov = new Image;
	codeNorm = new Image; 
	codeHov = new Image;
	formNorm = new Image; 
	formHov = new Image;
	homeNorm = new Image; 
	homeHov = new Image;
	pansNorm = new Image; 
	pansHov = new Image;
	wishlistNorm = new Image; 
	wishlistHov = new Image;
	
	//set the source properties
	introNorm.src = "images/intro.gif";
	introHov.src = "images/intro_hov.gif";
	codeNorm.src = "images/code.gif";
	codeHov.src = "images/code_hov.gif";
	formNorm.src = "images/form.gif";
	formHov.src = "images/form_hov.gif";
	homeNorm.src = "images/home.gif";
	homeHov.src = "images/home_hov.gif";
	pansNorm.src = "images/pans.gif";
	pansHov.src = "images/pans_hov.gif";
	wishlistNorm.src = "images/wishlist.gif";
	wishlistHov.src = "images/wishlist_hov.gif";
	}else{//create dummy variables for older browsers
  introNorm = ""; 
	introHov ="";
	document.intro="";
	codeNorm= "";
	codeHov= "";
	document.code="";
	formNorm= "";
	formHov= "";
	document.form="";
	homeNorm= "";
	homeHov= "";
	document.home="";
	pansNorm= "";
	pansHov= "";
	document.pans="";
	wishlistNorm= "";
	wishlistHov= "";
	document.wishlist="";
}

Older browsers (Netscape 2.0, Internet Explorer 3.0 and earlier) do not fully support the document object model and so will return errors when attempting to assign variables to the document.images object. A check is in place to prevent this whereby the varibles are instead assigned dummy values.

If support is present, the .src properties of each variable is set to the path to the appropriate image.

The chgImage() function:

function chgImage(imgFld, newImg){
	if (document.images){
	  //set the image in the image field to the image name passed as a parameter
	  document.getElementById(imgFld).src=eval(newImg + ".src")
		}
}

The function takes two parameters:

The .src attribute of the element holding the image is set to the source path to the new image.

The getElementById() method is used to indirectly access the appropriate element. This is more maintainable and forward compatible with the DOM than directly accessing the element e.g. document[imgFld].

The eval() method is used to convert the string (newImg + ".src") into an object.

Calling the function from main.html (Main page code)

<script src="external.js" language="Javascript" type="text/javascript">
</script>

The src attribute of the <script> element is used create the link to the external javascript file. The language and type attributes are also defined as javascript.

<li><a href="index.html" onmouseover="chgImage('intro', 'introHov')"
       onmouseout="chgImage('intro', 'introNorm')">
       <img src="images/intro.gif" alt="Intro link" width="152" height="24" 
			 border="0" name="intro" id="intro">
     </a>
</li>

The chgImage() function is assigned to both the onmouseover and onmouseout event handlers which are declared as attributes of the <a> elements which form the navigation links in the main.html page. The function serves to swap images appropriatley depending on whether the user mouse is currently hovering over an active link.

This process is repeated for active links on the navigation bar of other pages to maintain consistency throughout the site.

The <noscript> element

<noscript style="color: red ;">This site is best viewed with JavaScript!<br /> 
	Certain advanced features are not currently enabled.</noscript>

This is used to display a prominent warning in the content of the page informing non-javascript users that certain features will not work without javascript.

Credits/Modifications: The chgImage() function is based on code from Negrino and Smith: Javascript 5th Edition (chapter4, p75), but the script found there does not use getElementById() to indirectly access the element. I prefer this method as it represents a better object-oriented approach more in keeping with current developments regarding the DOM. It does require that the appropriate id attributes are set for elements within the page(s), but this is good practice anyway.

The calling of the function in relation to eventhandling is also based on various scripts from chapter 4 of the same book.The remaining code was written by me, based on general information from Study Guides 4 and 7.

Return to top


The Product Page

Opening a New Window for a Larger Image

Overview: Currently, the link for a larger image of a product references an image file for that product. An alternative would be to use javascript to open a new window which can then be coded to contain greater functionality.

In this example, the openImg() function is used to open a seperate HTML file containing the relevant image and an input button allowing the user to close the new window. When opened, the window always has focus and is non-resizable.

When closed, focus is always returned to the product1.html page. Closing the window is achieved via the closeImg() function.

The openImg() and closeImg() functions:

//fn to open a stated larger imagewindow
imgWin = null //create and initialize a variable to hold the new window object
function openImg(imgSrc){
imgWin = window.open(imgSrc,"largeWindow", "width=500,height=500");//create the new window
imgWin.focus();//force window to the front
}

//fn to close the new window. Should only be called from a new child window
function closeImg(){
 imgWin.close();
 self.focus();//force focus back to the parent window ie this window
}
  

The two functions are again declared in the external javascript page and both use the variable imgWin to reference a new window object. This is initialised initially to null (not all browsers do this automatically).

openImg() takes a path to the appropriate html file as a parameter and opens this file as a new window, with the name 'largeWindow' and its size set to contain the image and the exit button. The new window is given focus to force it to the front.

closeImage() is called from the new window and simply closes the window and returns focus to the product page.

Code For the New HTML Page That Holds the Large Image

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Large Picture</title>

</head>
<body>
  <!-- Insert the image -->
	<img src="images/large.jpg" alt="An image of a large pan" />
	<!-- Insert the close button. Calls fn from parent as Firefox insists only a script that 
	                                                          opens a window can close it -->
	<input type="button" value="Close the window" onclick="opener.closeImg()" />

</body>
</html>
	

The closeImg() function is assigned as the onclick event handler for the exit button on the page. It uses the opener property of a window object to reference the window that opened it - in this case the product1.html page. In this way, the closeImg() function is called from the product page which opened it. This is a requirement for the Firefox browser which will not close a window from a script which did not open it.

Non-Javascript Users

The <noscript> element provides warnings and a link to the original image for users not running JavaScript

<noscript>
	  <p>A <a href="images/large.jpg" target="_blank">larger image</a> is also available.
		 <span style="color: red ;">*Use this link*</span>
	  </p>
</noscript>
	

Credits/Modifications: The code is based on script 7.10 (Negrino and Smith, Javascript 5th Edition Chapter7), but has been adapted to open and close windows between parent and child windows using function calls between them.

Return to top


The Slideshow

Overview:The slideshow has been incorporated into the product page to replace the original static images. It essentially involves creating two arrays (one for images and one for captions), setting variables to store images in the cache and using two functions to navigate through the arrays in synchrony, either via the keyboard or the mouse.

The Caption Array:

  //create an array holding captions for the slideshow images
  //Position of caption in array must match position of image in images array for synchronicity
  captionArray = new Array ('Front view', 'Pan Lid', 'Side View', 'Whole Pan', 'Pan with Lid')

	

The code creates a simple array containing the string captions for the images in the slideshow.The position of each caption needs to correspond to the position of the image in the image array so that each remain in synchrony.

Create Variables and Assign the Source Path:

  //create variables to store images in the cache
  panFront = new Image;
  panLid = new Image;
  panSide = new Image;
  panSmall = new Image;
  panWithLid = new Image;

  //set the source path
  panFront.src = "images/front.jpg";
  panLid.src = "images/glasslid.jpg";
  panSide.src = "images/side.jpg";
  panSmall.src = "images/small.jpg";
  panWithLid.src = "images/withlid.jpg";
	

Images, stored in the cache, are assigned to variables and their src property is set to reference the images.

The Image Array:

//create a variable and inititialize it to an array of the images
prodViewArray = new Array (panFront.src, panLid.src, panSide.src, panSmall.src, panWithLid.src);
	

A second array is created and initialized to hold the paths to the images in the slideshow

The Array Variables:

//set a counter to 0
currPic = 0;
//set a count variable to count in line with the array ie starts at 0. Final pic is 
//the no of pics -1
picCt = prodViewArray.length - 1; 
	

Two variables are created that will be used to track the current index position and length in both arrays.

currPic stores the current index of the arrays. It is initialized to 0 - the start of the array

picCt stores the final index position of the arrays. It is initialized to array.length -1 to conform with JavaScripts array numbering system - arrays start at 0 and end at the length minus 1.

The chgSlide(direction) function:

function chgSlide(direction){
 if(document.images){//check browser understands images
   currPic = currPic + direction;//moves fwd or bwd depending on direction value
   if (currPic > picCt){//end of array
		 currPic = 0; //reset to start
   }
   if (currPic < 0){//start of array
		 currPic = picCt; //reset to end
   }	
   document.slideHolder.src=prodViewArray[currPic];//set the src for the placeholder for the slide 
	                                          //show to the array indexed at the new value
   document.getElementById("caption").value = captionArray[currPic];
 }
}	
	

The function takes a single numeric parameter which determines in which direction iteration through the array will occur. An intial check is made that the browser understands the images property(if not, no further action will occur). The current index value is set to the current value plus the value of the direction parameter. If this is positive the slideshow moves forward, if negative, it reverses.

To achieve a continual looping through the array, two further checks are made:

Finally, the function sets the values of the placeholder elements in the HTML for both the image (slideholder) and the caption (caption) in order to display the correct picture and caption in unison on the page.

The keyHit Function and Associated Code:

Firstly, the keyHit function is assigned to the onkeydown event handler

  document.onkeydown = keyHit//assign the onkeydown eventhandler to the keyHit function
	

Netscape 4 captures events differently to other browsers, so the document.layers property is used to check for NS4 (only NS4 defines the layers property). If the browser is NS4, the captureEvents() method is used to explicitly set up a 'listener' for KEYDOWN events. The numeric values for the left and right keyboard arrows (28 and 29 in NS4) are also assigned to variables.

If the browser is not NS4, these variables are set to 37 and 39, values appropriate to these browsers

	if (document.layers) {//check for NS4 browser
		document.captureEvents(Event.KEYDOWN)//capture the keydown event in NS4
		ltArrow = 28 //assign variables to the NS values for the 
		rtArrow = 29 //left and right arrows on the keyboard
	}
	else {//otherwise set the variables to the values generated in other browsers
		ltArrow = 37
		rtArrow = 39
	}
	

Finally, the keyHit function is defined:

//define the keyHit fn which takes a keydown event as a parameter
function keyHit(evt) {
	if (evt) {
		thisKey = evt.which //determines which key pressed in Netscape
	}
	else {
		thisKey = window.event.keyCode// determines which key pressed in Internet Explorer
	}
	//move the slideshow depending on which key is pressed
	if (thisKey == ltArrow) {
		chgSlide(-1)
	}
	else if (thisKey == rtArrow) {
		chgSlide(1)
	}
}	
	

This function takes a special variable evt which is generated when an event occurs. How to determine which event that was varies depending on which browser is being used. Netscape use the evt.which property, while Internet Explorer uses window.event.keycode. Two if blocks are therefore set up to check for both possibilities, and the resultant value is stored in the thisKey variable.

Depending on which key was pressed, the appropriate numeric value is then passed to the chgSlide() function causing the array to iterate either forwards or backwards.

Calling the Functions From the Product Page:

Initial advice is given on how to use the slideshow

<p>Use the links provided below (or the left/right arrows on your keyboard) to view 
different aspects of the pan.</p>
	
	

A <textarea> element is created and identified to hold the caption, while an image placeholder is created and named to hold the slideshow images. The naming and identifying are vital to allow the elements to be referenced from the chgSlide() function.

The <textarea> element contains the initial text 'Front View' corresponding to the initial image in the slideshow placeholder, which itself is directly referenced (rather than using the declared variables) as images/front.jpg. This is to ensure that non-javascript users will still see some initial values along with informational messages.

	<!-- Create a placeholder box to hold the captions -->
	<p align="center">
	<textarea cols="20" rows="1" readonly="readonly" id="caption">Front View</textarea>
	</p>
	<!--create a placeholder for the slideshow images-->
	<p align="center">
	  <img src="images/front.jpg" name="slideHolder" width="250" height="150" alt="slideshow" />
	</p>
	

Two links are created, next and previous, whose href attributes are set to call the chgSlide() function with the appropriate parameter passed in order to move the slideshow in the right direction.

	<!--create the links to move back anf forwards-->
	<h4 align="center">
	 <a href="javascript:chgSlide(-1)"><<Previous</a>  
	 <a href="javascript:chgSlide(1)"> Next >></a>
	</h4>
	

Non JavaScript Users:

An alternative (dummy) link is provided to a seperate HTML page containing all the images in the slideshow to ensure that they are still available to users without javascript. Informational messages are also included to ensure the user knows that the slideshow requires javascript to work.

	<noscript style="color: red">You need javascript to view the slideshow
	<p>For alternative images visit the seperate <a href="">images </a>page</p>
	</noscript>
	

Credits/Modifications: The chgSlide(direction) function is essentially the same code as defined in Negrino and Smith, Javascript 5th Edition, Chapter 5 Script 5.6, with a single line added to cater for updating a caption.

Similarily, the keyHit() function and associated code is taken from Chapter 11, script 11.10, with no modification.

The code for creating and updating the caption is essentially my own work, but the idea came from Script 16.6, Negrino and Smith, Chapter 16.

The Shopping Cart

Overview:The DOM (document object model) is used to dynamically create and delete elements allowing items to superficially be added and deleted from the the shopping cart.

A variable noOfItems is used to track the number of items added to the cart to prevent errors by attempting to delete items when none exist

noOfItems = 0;	 
	 

The addToCart() Function:

function addToCart(aProduct){
 if (aProduct == 'fryingPan'){
   aDesc = 'The 20 inch frying pan';
 }
 if (aProduct == 'somethingElse'){
  aDesc = 'something else';
 }
 newPara = document.createElement("p");
 withText= document.createTextNode(aDesc);
 //add the text to the new para
 newPara.appendChild(withText);
 //add the text to the cart/right div
 cartDiv = document.getElementById('right');
 cartDiv.appendChild (newPara); 
 noOfItems = noOfItems +1;
}
	 

The function takes a product as a parameter and then returns a description depending on that product. It then uses the DOM to create a new element containing that description as the content.

The createElement() method of document creates a new HTML element passed as a parameter. The createTextNode() method creates the text content for an element based on the parameter passed. In this case, it is the appropriate product description. This content is then added using the appendChild() method.

In order to place this new element correctly on the page, it must also be placed as a child element of the relevant page element. The getElementById() method is used to locate this element, and then the appendChild() method is used to add the new element to its position.

Finally, the noOfItems variable is updated to reflect the current number of items in the cart.

The removeFromCart() Function:

function removeFromCart(){
//rmove something from the cart/right div
 cartDiv = document.getElementById('right');
  if(noOfItems >0){
	 cartDiv.removeChild(newPara);
	 noOfItems = noOfItems -1;
  }
}
	 

After an initial check to ensure that any items exist, the removeChild() DOM method is used to remove an item from the cart. The noOfItems variable is then decreased accordingly.

Within the Product Page

The two functions are assigned to the onclick events of the add and delete buttons respectively

<p>
  <button type="button" onclick="addToCart('fryingPan')">Add</button>
  <button type="button" onclick="removeFromCart()">Delete</button>
</p>
	 

Credits/Modifications:Both functions are essentially my own work based on Negrino and Smith JavaScript 5th Edition; Chapter 17, study guide week 9; and DOM Scripting, Jeremy Keith, Chapter 7.

Return to top


The Form page

Form Field Validations

Overview:Five of the input fields on the purchase form require validation:

The central mechanism used to achieve this is the use of regular expressions. A regular expression is a pattern used to express a text string, which can then be checked against that pattern.

The first step is to create the regular expression patterns for each form field.

The Regular Expressions

The Street Name field: The regular expression declared is:

var regExpStreet=/^([A-Z]|[a-z])\D+$/; //must begin with capital/small letter 
				//followed by any non-digit
	

Step by step, we can interpret the expression as:

/ - indicates the start of the regular expression.

^ - indicates the start of a string.

() - indicates a grouping. Any modifiers will be applied to the whole group.

[A-Z] - indicates that any one character within the specified range can occur.

| - indicates one or other. So [A-Z]|[a-z] indicates that either a capital or a small letter can occur.

\D - indicates any non-digit character.

+ - indicates that the previous definition (i.e. a non digit character) must occur one or more times.

So essentially a street name must begin with either a capital or small letter (the specification made no distinction), and then be followed any non digit character

The Postal Code field: The regular expression declared is:

	var regExpPostCode=/^([A-Z]{2}\d{2}\s\d{2}[A-Z]{2})|([A-Z]{2}\d\s\d[A-Z]{2})$/;
				//must be of form AA11 11AA or AA1 1AA
	

Here the new placeholders can be interpreted as:

{2} - indicates the specific number of times the previous definition or group can occur (in this case any capital letter can occur twice)

\d - defines any digit 0 -9.

\s - represents a single white space character.

A post code format can be only AA11 11AA or AA1 1AA

The Phone field: The regular expression declared is:

	var regExpPhone=/^(\d{5}\s\d{6})|(\d{4}\s\d{7})$/;//must be of form 01234 567890 
						//or 0123 4567890
	

The format must be either 5 digits, a space followed by 6 digits or 4 digits, a space followed by 7 digits

A phone number can be only be of the form 01234 567890 or 0123 4567890

The Email field: The regular expression declared is:

	var regExpEmail=/^\w+@([a-z]|[A-Z])+([\.]?([a-z]|[A-Z]))*(\.([a-z]|[A-Z]){2,3})+$/;
				//fairly flexible- allows mk@bt.com or mk@ac.co.uk
				//but also allows mk@bt.co
				//Can be made more or less rigorous
	

This expression allows for fairly flexible entry.

\w+@ - one or more letters, numbers or underscores followed by a @

([a-z]|[A-Z])+ - one or more capital or small case letter.

[\.] - a full stop('.'). Since this is a special character with meaning within the regular expression itself, it must be escaped using the '\'.

? - the previous expression (ie the fullstop) can occur zero or 1 time. This allows emails with more than one full stop in the domain name, but does not require it.

([a-z]|[A-Z]) - again any capital or small letter

()* - both the [\.]? and the ([a-z]|[A-Z]) are then grouped and followed by a *. This allows a pattern like .ac.edu or .sports.football to be repeated 0 or more times.

(\.([a-z]|[A-Z]){2,3})+ - this grouping requires that a full stop must appear followed by either two or three letters 1 or more times. So an email must end with either .com or .uk etc.

The email allowed can be of various forms including mk@bt.com or mk@bt.co.uk

These regular expressions are then used in functions to validate the entries into appropriate input boxes.

The Validating Functions

Each field that requires validation has an associated function that checks its input. Three field have been coded to check validation when the form is submitted, whilst three are checked as the user inputs the data. Each set requires a slightly different approach.

Error messages are set up within <td> elements for each field, whose display style properties are set initially to none so they are not visible.

The Functions That Notify as The User Fills Out The Form

The validStreet() function:

//Function to test whether street name is correct on leaving the field
function validStreet(anInput){
	//test the street name
	if(regExpStreet.test(anInput.value)){
		 document.getElementById('errStreet').style.display='none'//hide the error message
  }else{//otherwise select appropriate field
		anInput.focus();
		anInput.select();
		document.getElementById('errStreet').style.display='block'//display the error message
  }
}
	

The function takes an input box itself as a parameter tests any value entered (anInput.value) against the pattern defined in the regular expression using the test() method of the regular expression object. If the pattern matches, DHTML is used to set the style property of the error message element to none ie invisible, in order to clear any previous error messages. If the pattern does not match focus is returned to the input box, any text is selected and the error message held in the errStreet element is set to block ie visible.

Similar functions are defined for all the other fields that check as the user inputs:

The validPostCode() function:

	
//Function to test whether postal code is correct on leaving the field
function validCode(anInput){
//test the post code name
	if(regExpPostCode.test(anInput.value)){
		document.getElementById('errPost').style.display='none'//hide the error message
	}else{//otherwise select appropriate field and return false	
		anInput.focus();
		anInput.select();
		document.getElementById('errPost').style.display='block'//display the error message 
	}
}
	
//Function to test whether credit card is correct on leaving the field
function validCard(anInput){
//test the credit card number
	if(regExpCreditCard.test(anInput.value)){
		document.getElementById('errCard').style.display='none'//hide the error message
		//return true; //if input is okay return true
	}else{//otherwise select appropriate field and return false	
		anInput.focus();
		anInput.select();
		document.getElementById('errCard').style.display='block'//display the error message
  }
}
	

On the form.html Page

Each appropriate function is called using the onblur event associated with each input field. This event fires when that field loses focus, so the input is checked as the user moves away from the field.

The this variable is passed as a parameter which acts as a self-reference to the input field defining the onclick event.

<td>Street Name</td>
<td><input type="text" name="shipStreetName" maxlength="30" onblur=" validStreet(this)"></td>
<td id="errStreet" style="color: red; display: none;">*Names must begin with a capital. 
  No numbers allowed.
</td>
				

The Functions That Check On Submitting The Form

Here, each function takes an input value as a parameter and tests it against the appropriate regular expression. If the input matches, any error messages are reset to dsplay:none and true is returned. Otherwise, false is returned. These functions must return a boolean to dictate whether or not a form will be allowed to submit or not.

The validPhone() function:

//Function to test whether phone is correct
function validPhone(aValue){
//test the phone
 if(regExpPhone.test(aValue)){
		document.getElementById('errBillPhone').style.display='none'//hide the error message
		document.getElementById('errShipPhone').style.display='none'//hide the error message
		return true; //if input is okay return true
	}else{//otherwise return false	 
    return false;//prevents form from submitting  
	}
}
	
	

The validEmail() function:

//Function to test whether email is correct
function validEmail(aValue){
//test the email
	if(regExpEmail.test(aValue)){
		document.getElementById('errEmail').style.display='none'//hide the error message
		return true; //if input is okay return true
	}else{//otherwise return false	 
    return false;//prevents form from submitting  
	}
}
	

Finally, a single function is defined which calls these validating functions, displays appropriate error messges and resets focus and re-selects text if the input is incorrect.

The submitIt()function:


/*CREATE A SINGLE FUNCTION THAT TESTS ALL RELEVANT FIELDS ON SUBMIT*/
function submitIt(aForm){
		
 //call the validPhone function shipping
 if (!validPhone(aForm.shipPhoneNumber.value)){//if validPhone() does not return true
	aForm.shipPhoneNumber.focus();//return focus to the shipping phone field
	aForm.shipPhoneNumber.select();//select the shipping phone field
	document.getElementById('errShipPhone').style.display='block' ;//display the error message
	return false;//prevent the form from submitting
 }

	
 //call the validPhone function billing
 if (!validPhone(aForm.billPhoneNumber.value)){//if validPhone() does not return true
	aForm.billPhoneNumber.focus();//return focus to the billing phone field
	aForm.billPhoneNumber.select();//select the billing phone field
  document.getElementById('errBillPhone').style.display='block' ;//display the error message
	return false;//prevent the form from submitting
 }
		
 //call the validEmail function 
 if (!validEmail(aForm.billEmailAddress.value)){//if validEmail() does not return true
	aForm.billEmailAddress.focus();//return focus to the email field
	aForm.billEmailAddress.select();//select the email field
	document.getElementById('errEmail').style.display='block' ;//display the error message
	return false;//prevent the form from submitting
 }
 	
 return true;//if all expressions pass then return true
}
	

The function takes a form as a parameter. Each input value is checked, and false is returned if the input is incorrect. This prevents the form from submitting with incorrect data. If all input is accurate, true is returned and the form submits the correct data.

The focus() and select() methods return the cursor to the appropriate field and any text is automatically selected.

This function is called on submitting the form. The this 'variable' is used as a self reference at runtime.

<form method="post" action="http://telemat.open.ac.uk/tt281/testform/decode_form.cfm" 
name="orderForm" onsubmit="return submitIt(this)">

Credits/Modifications: The general mechanism for validating a form by declaring 'subfunctions'which are then called by a single function onsubmit is based on the code as defined in Negrino and Smith, Javascript 5th Edition, Chapter 8 Script 8.11, but regular expressions have been used to test patterns as they provide greater flexibility.

Tne use of onblur to test input as the form is completed is essentially my own work based on information in study guides 6, 7 and 9. It should also be noted that their are known problems associated with the Firefox browser concerning re-selecting and re-focusing the text when using this technique.

Return to top


The Wish List Page

Overview:The cookieVal() method is used to obtain the value for the wishlist cookie. This value contains information regarding:

Each piece of information is seperated within the cookie value by a particular character entity (e.g. '=' or ':'). The string method split() can therefore be used to extract the information and store it in arrays.

By assigning these values to variables, document.write() methods can be used to build up the HTML necessary to display the actual page.

Some manipulation of the information is also required. This mainly involves concatenation in order to obtain correct structures for displaying the images and the page links

The Code

	//create a variable to hold the wishlist cookie value
	wishValue =unescape(cookieVal('wishlist'))
	//seperate out each wish product
	wishProductsArray = wishValue.split('&')
	

cookieVal returns the value for the wishlist cookie, and unescape() is used to allow for any special characters. The cookie value contains information regarding several wishlist products, each seperated by an '&'. Consequently, the split('&') method is used to seperate each wishlist item into the wishProductsArray.

	//split each element on : so that the pan name is at element 0 and prodDesc/prodpage is at 1
	prodName1 = (wishProductsArray[0].split(':'))[0]
	prodName2 = (wishProductsArray[1].split(':'))[0]
	prodName3 = (wishProductsArray[2].split(':'))[0]
	prodName4 = (wishProductsArray[3].split(':'))[0]
	

Within the information for each product, a ':' is used to seperate the product name from the rest of the details. Again document.split(':') is used to access this information. The name will be held at index [0], and so this is accessed via array[0] and assigned to a variable for each product.

The path for the image sources required for the page can be determined using the product name as the are all of the form:

The next step is therefore to set up the source information for all the images in the wishlist

prod1Image = new Image;
//create a path to the image
prod1Image.src = "images/" + prodName1 + ".jpg";
	
prod2Image = new Image;
//create a path to the image
prod2Image.src = "images/" + prodName2 + ".jpg";

prod3Image = new Image;
//create a path to the image
prod3Image.src = "images/" + prodName3 + ".jpg";

prod4Image = new Image;
//create a path to the image
prod4Image.src = "images/" + prodName4 + ".jpg";
	

The product description and reference page information are also stored in the wishProductsArray, but at index[1]. This information is retrieved and assigned to a variable. A '=' character entity is used to seperate each description from each page reference, so again the split() method (.split'=') is used to access each piece individually, and assign the result to a variable.

//split each element on : so that the pan name is at element 0 and prodDesc/prodpage is at 1
descAndname1 = (wishProductsArray[0].split(':'))[1]
descAndname2 = (wishProductsArray[1].split(':'))[1]
descAndname3 = (wishProductsArray[2].split(':'))[1]
descAndname4 = (wishProductsArray[3].split(':'))[1]

//split each descAndName on = so that desc is at 0 and page name is at 1
desc1 = (descAndname1.split('='))[0]
page1 = (descAndname1.split('='))[1]

desc2 = (descAndname2.split('='))[0]
page2 = (descAndname2.split('='))[1]

desc3 = (descAndname3.split('='))[0]
page3 = (descAndname3.split('='))[1]

desc4 = (descAndname4.split('='))[0]
page4 = (descAndname4.split('='))[1]
	

Creating the Page

The setWishImages() function is defined to set all the images for the page. It uses the chgImage() function defined earlier to place a given image in a given location on the page.

//create a fn that sets the images/text/link for the wishlist
function setWishImages(){
 //set the prod1 image with chgImage
 chgImage('prod1ImageHolder', 'prod1Image')
					
 //set the prod2 image with chgImage
 chgImage('prod2ImageHolder', 'prod2Image')
		
 //set the prod3 image with chgImage
 chgImage('prod3ImageHolder', 'prod3Image')

 //set the prod4 image with chgImage
 chgImage('prod4ImageHolder', 'prod4Image')
 //create a new para with desc4 as the text			
}

A table is defined within the middle <div> to hold the wishlist information. Each row cntains the information for each wishlist product. One <td> cell within each row is identified as a placeholder for the product image. A second <td> cell is also defined to hold the product description and page link information. A document.write method is used to write out the HTML with the relevant information incorporated (using the '+' concatenation operator) to display the page accordingly.

<tr><!-- create a place holder for wishlist1 -->
  <td><img src=" " id="prod1ImageHolder" alt="wish list image" /></td>
  <td>
    <script type="text/javascript">
    <!--
      document.write("<p>"+desc1+"</p>")
      document.write("<a href='" + page1 + ".html'>Link</a>")
    // -->
    </script>
  </td>
</tr>

This information is repeated for the other wish list products.

<tr><!-- create a place holder for wishlist2 -->
  <td><img src=" " id="prod2ImageHolder" alt="wish list image" /></td>
  <td>
    <script type="text/javascript">
    <!--
      document.write("<p>"+desc2+"</p>")
      document.write("<a href='" + page2 + ".html'>Link</a>")
    // -->
    </script>
  </td>
</tr>
<tr><!-- create a place holder for wishlist3 -->
  <td><img src=" " id="prod3ImageHolder" alt="wish list image" /></td>
  <td>
    <script type="text/javascript">
    <!--
      document.write("<p>"+desc3+"</p>")
      document.write("<a href='" + page3 + ".html'>Link</a>")
    // -->
    </script>
  </td>
</tr>
<tr><!-- create a place holder for wishlist4 -->
  <td><img src=" " id="prod4ImageHolder" alt="wish list image" /></td>
  <td>
    <script type="text/javascript">
    <!--
      document.write("<p>"+desc4+"</p>")
      document.write("<a href='" + page4 + ".html'>Link</a>")
    // -->
    </script>
  </td>
</tr>

In order to set the images, the setWishImages() function is called when the page loads

<body onload="setWishImages()">

Credits/Modifications: Most of the work to generate the wish list page is essentially original. However, the technique of iterating through arrays and precipitating out relevant information is based on Script 12.4, Javascript 5th Edition, Negrino and Smith.

The general techniques associated with accessing arrays and manipulating strings are based on the programming guide associated with study guides 2 and 3, and general reference to The JavaScript Bible (Goodman, Danny) and JavaScript, The Definitive Guide (Flanagan, David).

Return to top