Script School Classroom

School Map:  Home / Enroll $ Student Records; Class  
$ News @ LIVE Tech Radio * Support/FAQ | Store | FORUMS

Script School Course #7 - JavaScript -  Week #4

Printable Version of this page HERE

Storing Information in Cookies and Hidden Frames

Keeping State with Cookies and Hidden Frames

HTML is 'stateless', that is, each anonymous page view is unrelated to other page views.  Often You'll want to set a cookie that only lasts the length of a viewing session, to keep track of information as Your user visits different pages on Your site.  This is known as 'keeping or maintaining state'.  We'll also take a brief look, after we discuss Cookies, at another way of keeping state during a site visit - using a hidden frame.  Just as an aside, many server languages, including php, have what are known as 'session variables' which maintain state.

About Cookies

What are Cookies?

Cookies are a way to store small amounts of information on Your user's computers. They are a property of the page's window document object.

What are Cookies good for?

Cookies are useful for non-critical information pertinent to each user.  Users can block Cookies or delete them, but, since many sites 'require' Cookies and since they are 'safe' - can't spread viruses - most users accept them.  They can save space and processing on Your server.  If they are not deleted they can persist for many years.  Cookies can be used to store user preferences, create a shopping cart, or to keep the time and date of each visit and show 'what's new' flags.  Many affiliate programs use Cookies to credit sites that refer customers to them.   They can be used to fill in information in forms, such as name, phone number, email, snail mail address, etc.  They can also provide a way to save users from typing in a username and password on every visit, to 'log them in', to 'know' who is visiting Your site {this is not a secure method - Cookies can be 'spoofed': written by hackers onto their own machines - don't use Cookies in critical situations!!!}.   Advanced Students: If You use a log-in cookie, You may want to encrypt it to an md5 or similar hash with a server script. 
See: http://www.faqs.org/rfcs/rfc1321.html 

Where Can Cookies be Used?

Cookies can be set and recovered both through client side JavaScript and Server Scripts. Cookies are stored by different browsers in different places on the user's harddrive, so if a user has several browsers each browser will usually only set and get it's own Cookies.  And, of course, Cookies are only available on the machine they are set on, so a visit to Your site with a different computer B won't have the user's Cookies that were set on computer A.  Cookies can only be seen by the Domain that they are set to.  There are also Path considerations, discussed below.

How Big are Cookies, How Many can I have?

Cookies are of limited size and number.  The typical minimum most browsers accept is: • 300 Cookies • 4 kilobytes per cookie for name and value. • 20 Cookies per server or domain. Completely specified hosts and domains are considered separate entities, and each has a 20 cookie limitation.  If a user 'collects' too many Cookies, the oldest ones may be deleted automatically by the browser to make room for new ones.  It is considered good web coding etiquette to combine Your information and set fewer Cookies - to 'help save cookie space'.

What's in a Cookie?

All Cookies have a Name and a Value.  These are essential to create a valid cookie.

Cookies have Expiration Dates.  If the Cookie isn't set to expire at a time in the future, the cookie will expire at the end of the browsing session.

Cookies are associated with a given Domain and Path.  If these are not supplied, the default is the Domain and Path of the page that sets the cookie.  Higher paths can't access Cookies set to a lower path, but lower paths have access to higher paths in their tree.  So Path '/' can set cookies that can be read from Path '/Forms/' but cookies set from Path '/Forms/' can't be read from Path '/'.  You may wish to set the Path to '/' in Cookies set by page 'www.mysite.com/Forms/UserForm.html'.  Cautionary Note: Moving pages to other directories on Your server which don't set the Path to '/' can 'loose' Cookies - pages on Your site may no longer be able to read from or write to them. 

You can also set a 'security' parameter that will only share Cookies with the server if the connection is HTTPS.  As mentioned, Cookies can be set and recovered by both Client Side JavaScript and Server Side Scripts.  When a client requests a page, all Cookies set to that domain are sent to the server, if allowed by the security parameter.  Server Scripts can set Cookies in the Headers that are sent with the page.

Setting a Cookie

Cookies can be set by JavaScript at any time during a page visit, this differs from Server Side Scripts, which only set cookies when the page loads.  The syntax of a Cookie is:


   document.cookie = "CookieName=CookieValue[;expiries=Date][; path=Path][;domain=Domain][; secure]";
   

Words in italics indicate names or values You supply. Bracketed expressions are optional. Bold indicates standard keywords and operators.

The CookieValue should be 'escaped' for characters that may interfere with HTML.  JavaScript provides a Method to do this aptly called:   escape()   When You are ready to extract the Cookie You can use:  unescape()   The Date parameter should be in a specific form which is provided by applying the Method:  toUTCString()   to an instance of the Date() object. See Week 2 of this course for more about the Date() object.

General function to set a Cookie:

 
   // place within <SCRIPT> tags in the <HEAD>
   // days: unquoted Number, secured: unquoted true or false, all others: quoted Strings 
   // name & value required
   // if days omitted defaults to Cookie expiring after 1 day
   // if path omitted defaults to '/' or the top level path for the domain
   // if domain omitted defaults to server domain
   // if secured omitted defaults to transmit Cookie to server over any connection
   
   function MakeCookie(name, value, days, path, domain, secured)
   {      
      var expire = new Date();
      if(!days){
         var days = 1;
      }
      expire.setTime(expire.getTime() + days*24*60*60*1000);
      document.cookie = name + "=" + escape(value) +
      "; expires=" + expire.toUTCString() +
      ((path) ? "; path=" + path : "") +
      ((domain) ? "; domain=" + domain : "/") +
      ((secured) ? "; secure" : "");
   }
	  

In our MakeCookie() function we encounter a few techniques we have not seen in this course yet. 

The structure:  conditional ? expression_if_true : expression_if_false  is a shorthand substitute for a simple if structure. When only a variable or function argument is placed into the conditional, it's existence is determined - true or false.

The NOT operator:  !  determines the opposite. In this example we can read the if statement as: "if the function argument 'days' does NOT exist, set a variable called 'days' to the number 1"

First we create a new instance of the  Date()  object as 'expire'.  After checking for the 'days' argument or setting it, we reset 'expire' to the desired expiration date, using 'days'.  Note: this is done in milliseconds
We  escape()  the value argument.
'expire' is formatted with  toUTCString() 

A function to check form input:

 
  
   // place within <SCRIPT> tags in the <HEAD>
   // function checks for input error: if no error it calls the MakeCookie() function
   
   function ClearCookieInput(name, value, days, path, domain, secured)
   {
      if(!isNaN(value))
      {
         alert("Please Enter Your Name, \n\n\t Thank You");
         // change to suit:
         // SetCookie is the name of the form used on this page
         // uname is the name of the text box used in this form
         document.SetCookie.uname.value = "";
         document.SetCookie.uname.focus();
         return;
      }
      MakeCookie(name, value, days, path, domain, secured);
   }

The ClearCookieInput function takes all the arguments that will be sent to the MakeCookie() function.  It checks the 'value' argument using the JavaScript Method:  isNaN()  which returns true if it's argument cannot be resolved to a number. We use the NOT operator  !  to reverse the result...   if(!isNaN(value))   since we want to respond to a situation when we are getting a 'value' that is resolved to a number - which would make the entry unacceptable. A blank entry resolves to zero, a number. 

If the entry is not acceptable:
   1)  An  alert()   is sent. (see Week 1 of this course)
   2)  The value of the text box in the form is cleared
   3)  The text box is given  focus()  which sets the prompt to the text box
   4)   return   ends or 'jumps out' of  the function, returning nothing.

If the entry is acceptable:
   1) the MakeCookie() function is called, passing all the arguments:  MakeCookie(name, value, days, path, domain, secured);   This also demonstrates how to call one function from within another.  After this call, the MakeCookie() function runs.

In the <BODY> to set a Cookie:



   <FORM  name="SetCookie" onSubmit=”return true”>
   Enter your name:
      <INPUT TYPE="text" NAME="uname" SIZE=20  onFocus="this.form.uname.value = ''">
      <INPUT TYPE="button" value="Set Cookie"
      onClick="ClearCookieInput('ScriptSchoolTestCookie', this.form.uname.value)">
      style="color:#009900; background-color:#EEFFEE"
   </FORM>

Within a <FORM> we provide a text box called 'uname' and a button that calls the ClearCookieInput() function when it is clicked.  We set the name of the Cookie to: 'ScriptSchoolTestCookie'.  We send 'this.form.uname.value' - the value of the textbox - as the 'value' argument for the Cookie.  'this.form.' refers to the  <FORM>  where 'this.form.'  is used.  Since none of the other arguments are included in the call to ClearCookieInput() the default settings will be used.

Enter your name:    
(You'll see the results below, at the end of the 'Retrieving Cookies' section.  Don't worry, there is also a 'Deleting Cookies' section!)

Retrieving a Cookie

Getting a cookie is more complex than setting one.  All the Cookies set by the browser for Your server's domain/path exist as a single String. You must search the Cookie String for the Cookie You wish to recover.  Strings of Characters can be addressed character by character, beginning at zero. To do this, the following function uses the JavaScript String methods:

  1.  objectString.length  returns the length of, or the total number of characters in, the given objectString.

  2.  indexOf()  returns the position of argumentString within the objectString it is applied to, counting from zero:  objectString.indexOf(argumentString[, fromIndex])  It returns -1 if the argumentString isn't found. The optional fromIndex integer starts the search from that position instead of zero.

  3.  objectString.substring(startIndex, stopIndex)  returns a portion of the objectString from startIndex to one character before stopIndex, counting from zero.

We use, for the first times in this course:

  1.  !=  comparison operator, which means 'not equal'

  2.  +=  assignment operator or:  thisVariable += value , which is the same as: thisVariable = thisVariable + value There is also a  -=  operator which subtracts the value from the variable and then assigns the results back to the variable.  *=  ,  /=  ,  %=   similarly multiply, divide, or get the modulus (remainder of a division) and assign it back to the variable.

You will recall that the comparison operator used to check for equal values is two equal symbols  ==   Don't confuse it with the single equal symbol  =  which is used as the basic assignment operator... to assign variables their values.

General function to retrieve a Cookie:


   // place within <SCRIPT> tags in the <HEAD>
   function GetCookie(Name)
   {
      // document.cookie is an object do not use quotes
      var dc = document.cookie; 
      // add '=' to Cookie Name, set as variable 'find'
      var find = Name + "=";
      // if there are any cookies...
      if (dc.length != 0)
      { 
         // start gets the location of find or Name=
         var start = dc.indexOf(find);
      }
      // if Cookie Name found...
      if (start != -1)
      { 
         // set start to beginning of value
         start += find.length;
         // set stop to end of cookie value
         var stop = dc.indexOf(";", start);
         // if indexOf ';' not found after start...
         if (stop == -1)
         {
            // stop gets the value of the entire document.cookie length
            stop = dc.length;
         }
         // return the unescaped value of the substring from start to one character before stop
         // recall that we initially escaped the value when we set the Cookie	
         return unescape(dc.substring(start, stop));
      }
   }

Specific to this page:


   // place within <SCRIPT> tags in the <HEAD>
   function ShowCookie(name)
   {
      // provide Your own location for the value returned:
      document.ShowCookieForm.DisplayCookie.value = GetCookie(name);
   }

Here, for the first time in this course, we see how to use a value that is returned from a function. If the GetCookie() function finds a value, it's last line:  return unescape(dc.substring(start, stop));   returns the value.  In the ShowCookie() function we assign the value returned from GetCookie() to the text box in the ShowCookieForm:  document.ShowCookieForm.DisplayCookie.value = GetCookie(name); 

In the <BODY> to get a Cookie:


   <form name="ShowCookieForm" onSubmit="return true;">
      <input type="button" value="Get Cookie" onClick="ShowCookie('ScriptSchoolTestCookie')"
      style="color:#0000FF; background-color:#EEEEFF">
      <input name="DisplayCookie" type="text" size="20" readonly="true">
   </form>

  Enter your name:  (repeated for convenience)
       
   
(To see that the Cookie has really been set: Close Your Browser, return to this page within one day, and Press the 'Get Cookie' button.)

Deleting Cookies

        (Purposefully shown out of our normal sequence... Watch text box next to 'Get Cookie' button, above.)

To delete a Cookie, set it's expiration date to a time in the past.

General function for deleting Cookies:


   // place within <SCRIPT> tags in the <HEAD>
   function DeleteCookie(name, path, domain)
   {      
      var expire = new Date();
      expire.setTime(expire.getTime() - 1000);
      document.cookie = name + "=" + "" +
      "; expires=" + expire.toUTCString() +
      ((path) ? "; path=" + path : "") +
      ((domain) ? "; domain=" + domain : "/");
      // determine if the ShowCookie function exists...
      if(ShowCookie)
      {
         ShowCookie(name);
      }
   }

In the <BODY> to delete a Cookie:


   <form name="DeleteCookieForm">
      <input type="button" name="Button" value="Delete Cookie"
	     onClick="DeleteCookie('ScriptSchoolTestCookie')" 
		 style="color:#FF0000; background-color:#FFEEEE">
   </form>

Using Frames to Keep State

As mentioned at the very beginning of this week's class, HTML is stateless, that is, it has no built in way to keep track of information from page to page during a browser session at Your site. We have already seen how to use Cookies to store information - but what if Your users don't accept cookies?  There is another way... use a 'permanent' frame like You might for a navigation bar or use a 'hidden' frame.  Frames are just like Windows that all appear within a single browser view.  You can use JavaScript to communicate between Frames just as You can between Windows.  (see week 3 of this course)

Frames exist within a 'special' HTML page that constructs the Frameset.  Frameset pages have the following structure:


   <HTML>
   <HEAD>
   <TITLE>Site Title</TITLE>
   </HEAD>

   <FRAMESET COLS="250, *, 0" FRAMESPACING=0 FRAMEBORDER=0 BORDER=0>
      <FRAME NAME="Navigation" SRC="Nav.html" SCROLLING="NO" MARGINWIDTH="0">
      <FRAME NAME="Main" SRC="Home.html" SCROLLING="YES" MARGINWIDTH="0">
      <FRAME NAME="Hidden" SRC="Hidden.html" SCROLLING="NO" MARGINWIDTH="0">
   </FRAMESET>

   </HTML>

As You can see there is a <FRAMESET> tag, and not a <BODY> tag.  We have set the Frameset to have a left column of 250 pixels for a navigation bar, a center column designated with a size of  *  that will stretch to take up the rest of the screen, and on the right side a 'hidden' frame of 0 pixels in width.  Although the hidden frame won't appear, it can be addressed like any other frame or window.  We also set all the frame borders, margins and spacing to zero, somewhat redundantly, to adjust them on as many browsers and platforms as possible.  This results in a 'seamless' view.

Each frame has at least one HTML page assigned to it.  In the page for the Hidden frame we create some variables to hold values through the browser session:


   <HTML>
   <HEAD>
   <TITLE>...</TITLE>
   <SCRIPT LANGUAGE=JAVASCRIPT TYPE="TEXT/JAVASCRIPT">
   <!--
      var fname = "";
      var pagecount = "";
      var colorpref = "";
   // -->
   </SCRIPT>
   </HEAD>
   <BODY></BODY>
   </HTML>

   

 

Note: On page 2 shown in the scripts above, we breifly introduce the Array.  Arrays are like containers for multiple Variables.  Like the String, their index begins at zero.  They are addressed by an integer index within square brackets [ ].  If we have an array 'cubbyholes' we can address cubbyholes[0], cubbyholes[1] through the total number of 'subvariables' in the array.  JavaScript has a set of Methods to manipulate Arrays.  We will be examining them in greater detail in the future.

Assignments for this Week

Basic Assignment

Create a counter using a Cookie to keep track of page hits.

Advanced Assignment

Show communication between Frames or Windows that share a variable.  If You use Frames make the one with the variable 'hidden'.

Need help with your assignment or have questions about this week's course?

About The Instructors

TDavid is co-owner, programmer and webmaster for several sites devoted to programming including his own http://www.tdscripts.com/ He has done custom programming in various programming languages for companies all over the world. Every Friday at 2pm PST you can catch his weekly radio show dedicated to the technical side of webmastering and programming at http://www.scriptschool.com/radio/

LogSpirit is a student of Script School, the co-author of this course and available for hire for custom programming.

Printable Version of this page HERE

School Map:  Home / Enroll $ Student Records; Class  
$ News @ LIVE Tech Radio * Support/FAQ | Store

Advertising | Link To Us | Privacy 
Copyright 2000-2002 Script School Productions / KMR Enterprises 
No part of this website may be reproduced, copied and/or distributed in any medium 
without express written permission