Home » Web Development » 06 - Dynamic HTML and Cookies Using Javascript
6

A Session Cookie that Remembers The User's Favorite Flower

How to set session cookies based on user's preference using javascript

Finally, let us use the document.cookie hierarchy to set a session cookie based on a flower the user likes and use DHTML to display a picture of the flower on all our pages. This cookie is reset whenever the user closes all browser windows. Navigate to the register.htm page. Enter valid data and submit the form. You will see an image of the flower in the top bar. This image corresponds to the flower that appears first on the form amongst the flowers you checked under 'flowers you like' before you submitted the form. This image follows you through the web site and is reset when you select a new flower and submit the form or when you close all your browser windows.

Screenshot 6c: Home Page with Favorite Flower

Screenshot 6c: Home Page with Favorite Flower

The validate function in the registration form contains code that sets a cookie on the client computer. This cookie is read whenever a new page is loaded and its contents are used to display an image of a flower that the user likes. Cookies contain (a) series of name value pairs that represent information that is relevant to the web site that wrote them, (b) an optional time stamp that specifies the expiry date (a cookie without a time stamp is stored in a temporary folder and deleted at the end of the session) and (c) a path or sub path of the site where the cookie is valid. A cookie from www.someplace.com with a path set to "/tutorials" may only be accessed by pages that contain the entire path in their URL, in this case, all the pages under http://www.someplace.com/tutorials. Not setting the path allows all pages on the site to access the cookie's information. Cookies are written as name value pairs separated by semicolons. Let us look at the code that calls the cookie writing function on register.htm and the cookie-writing function itself.

for (i=0;i<document.forms.register.likes.length;i++)
{
    if (document.forms.register.likes[i].checked)
     {
        flowerSelect = true;
  favFlower = document.forms.register.likes[i].value;
  break;
      }
 }

if (flowerSelect == false)
  {
    alert("Please check at least one flower that you like");
 return false;
   }

 setCookie(favFlower);
 return true;
 

The highlighted code in the section above is from the validate function. The first highlighted line sets the favFlower variable to the name of the first checked flower. The second highlighted section calls the setCookie function. The setCookie function takes the first flower checked by the user as input and set the 'flower' cookie equal to its name. In other words, ir simply sets the document.cookie string to flower=flowername where flowername is rose, lily, tulip, or orchid - the members of the 'likes' checkbox group. We do not set an expiry date or a path for the cookie as we want it to expire at the end of the session and be valid in all branches of the site.

function setCookie(flowerName)
{
  document.cookie = "flower=" + flowerName + ";";
}

The get cookie function returns the value of the cookie whose name is passed into the function as an input parameter. Although our cookie is very simple, we have used a generic function that can tackle long cookie strings.

function getCookie(name)
{
    var cookieValue = " ";
 if (document.cookie.length>0)
     {
    var cookieArray = document.cookie.split(';');
         for(i=0;i < cookieArray.length;i++) 
   {
            var nameFound = cookieArray[i].indexOf(name + "=");
   if( nameFound != -1)
   {
     cookieValue = 
     cookieArray[i].substring(name.length+1,cookieArray[i].length);
   }
    }
       }
     
    return cookieValue;
}
  • If the document.cookie string is not empty, a cookie has been written for the page.
  • The getcookie function uses the Javascript 'split' method to first split the entire cookie string into an array of name value pairs. The split method takes a delimiter as an argument (semicolon for our cookie string). The string is split where ever this delimiter is found. Pieces of the string on which the method was applied (document.cookie in this case) are stored in an array.
  • Next, the indexOf method is run on each member of the array to see if the member contains the cookie we are searching for. The indexOf method searches for a substring (specified as its argument) in the string onto which it is applied. If a match is not found, the method returns -1. Otherwise, it returns the index (counting from 0) at which the match occurs. For example, "apples".indexOf("les") would return 3.
  • If our cookie is found, the substring method is used to return just the value of the cookie - in our case, this is one of four flower names. The substring method takes two index positions as arguments and returns the substring that starts at the first index and ends at the last index. Here, we use 'name.length+1' as the first argument to leave out the name of the cookie and the equals sign and get the rest of the string.
function displayFav()
{
   if (!isDHTML) return;
   
   var favoriteFlower = getCookie("flower");

   if (favoriteFlower == "" ) return;

   for(var i=0;i<flowerFav.length;i++)
      {
 
     if (flowerFav[i].src.indexOf(favoriteFlower) != -1)
     {
    
     flowerNum = i;
     break;
     }
   }
   document['favimage'].src = flowerFav[flowerNum].src;
   var favoriteDiv = new getDivObject("favoritediv");
   favoriteDiv.style.visibility = "visible";  
}

The displayfav() function is called when the body of the html page is loaded as follows:

<body onLoad="displayFav()">
  • The displayfav function returns if the browser does not understand DHTML.
  • If the browser is DHMTL compatible, it uses getCookie("flower") to get the value of the cookie with name "flower". If the cookie was not set, the function exits.
  • The flowerFav array is an array of images. Creating such arrays and populating them is referred to as image preloading. Image preloading is necessary because the value of the cookie is checked and the image displayed after the page is loaded. The register page and florist home page do not contain the images we need as part of the HTML. How do we get these images after the page has already gone to the client? We preload the images for later use as a solution. An image object contains a src (source) property that a string path to the image. Preloaded images travel to the client with the HMTL document.
if(document.images)
 {

        flowerFav=new Array(4);

  flowerFav[0] = new Image();
  flowerFav[0].src = "images/redrose.png";
   
     .. and so on .....

  flowerFav[3] = new Image();
  flowerFav[3].src = "images/tulip.png";
  
    }
  • If the cookie was set, displayfav() cycles through the flowerFav array to find an image that matches the name of the flower in the cookie. The 'src' property string of each image is searched for an occurrence of the name of the flower - we have followed a naming convention of naming the images after the corresponding flowers - and once again, the indexOf method is used to find a match.
  • If a match is found, the flowerNum variable is set to the index of the corresponding image and the 'break' statement is used to jump out of the loop.
  • The markup below corresponds to the markup for the div element that contains the image pertaining to the user's favorite flower. Note that it is set to be invisible and that the img tag within it of named 'favimage' initially contains a blank placeholder image. The ID of this div is set to "favoritediv"

<div id="favoritediv"  style="position:absolute;top:10;left:400;]
visibility: hidden"><
img src='images\blank.gif' height=70 alt='flower' name=favimage>
</div>  

  • The final lines of the displayfav function access the blank placeholder image and replace it with a appropriate preloaded image. The getDivObject method is used to access the div mentioned in the previous step (this div contains the image named favimg) and the div is set to visible.

document['favimage'].src = flowerFav[flowerNum].src;
var favoriteDiv = new getDivObject("favoritediv");
favoriteDiv.style.visibility = "visible";  

Image preloading is not necessary for the catalogue page; all the images are already on the page. So, on the catalogue page, the preload array is not declared and document['favimage'].src is set to the source of the corresponding flower image on the document.

The effect of adding all the Javascript to our html page makes the page look quite befuddling when its source is viewed. A skeleton page becomes more important in cases like this; any changes to a web site may be changed on the skeleton and the navigation markup and header scripts on each page may simply be replaced with the skeleton. However, the unique scripts on each should be taken note of; these scripts should be propagated after each change.

We are now ready to move on to the next level of web development - server side programming and scripting. We will learn how to load values from a database into a page, maintain a server side session, create and maintain a virtual shopping cart and more using in the next few chapters.