Section 8.2. All About Cookies


8.2. All About Cookies

Why cookie? The original name for a cookie came from the term "magic cookie"a token passed between two programs. Though accessible from JavaScript, cookies aren't really script-based: they're a mechanism of the HTTP server. As such, they're accessible by both the client and the server.

Whatever the name, cookies are small key-value pairs associated with an expiration date and with a domain/path, both of which are meant to ensure that the right cookies are read by the right servers. The information they contain is transmitted as part of the web-page request, and thus the data is available to the server and to the browser.

8.2.1. Storing and Reading Cookies

Cookies are accessible, like most other browser elements, through the document object. To create a cookie, you'll need to provide a cookie name, or key, an associated value, a date when it expires, and a path associated with the cookie. To access it, you'll access the document cookie and then have to parse the cookie out.

Luckily there's a plethora of cookie functions out and about. To get a better idea of how they work, I'll provide a variation of functions for setting, getting, and erasing a cookie and explain what happens with each step in the process.

To create a cookie, just assign the document cookie value a string with the following format:

cookieName=cookieValue; expirationdate; path

The cookie name and value are whatever you want and need, as long as the value is a simple value. I've used cookie names starting with a dollar sign ($cookieName), with an underscore (_cookieName), and other characters. Regardless of what a browser will accept, you won't want to use the equals sign (=) or semicolon (;), or your cookie functions most likely won't work.

I've also experimented with different cookie values, and depending on the browser, what gets attached to the cookie name is the string conversion of whatever the object isnumber, array, or object. However, this varies significantly between browsers. Figure 8-1 displays the document.cookie as printed out in Safari, Figure 8-2, as it's printed out in Firefox, and Figure 8-3 in Internet Explorerall from the same Mac computer, run one right after another, and all setting the same cookie values.

Figure 8-1. document.cookie string in Safari


Figure 8-2. document.cookie string in Firefox


Figure 8-3. document.cookie string in Internet Explorer


To ensure consistent results, I would recommend that you use primitive types (string, boolean, and number), converted to string only.

JavaScript Best Practice: Use simple types for cookie values.


As for the rest of the document cookie-setting string, the expiration date must be in a specific GMT (UTC) format. Creating a date object and then using the toGMTString is sufficient to ensure the date works. If no date is provided, the cookie is eliminated as soon as the browser closes.

The cookie path is especially important. The domain and path are compared with the page request, and if they don't sync up, the cookie can't be accessed or set. This prevents other sites from accessing any and all cookies set on your browser, though as you can see, this has been circumvented in the past.

A path setting of path=/ sets the cookie's allowable path to the top-level directory at your domain. If you access the page at http://somedomain.com, this means that the cookie is accessible by any subdirectory off of http://somedomain.com. If you specify a subdirectory, such as path=/images, the cookie is accessible only from web pages in this subdirectory. Conversely, if you have many subdomains at your web site, such as sub1.somedomain.com, sub2.somedomain.com, and so on, you can make a cookie accessible at all of them by specifically giving the higher-level domain: path=somedomain.com.

It's important to be selective about where your cookies are accessible. Be restrictive by setting your path to the topmost level essential for your application.


The following code snippet shows an example of a JavaScript function that sets a cookie to a specific key and value, but uses the same date (in 2010) and sets the path to the top-level subdirectory:

function setCookie(key,value) {    var cookieDate = new Date(2010,11,10,19,30,30);    document.cookie=key + "=" + escape(value) + "; expires=" + cookieDate.toGMTString(  ) + "; path=/"; }

The escape function is used to escape any special characters that might be part of the cookie value. This makes your cookie more secure, as we'll discuss later in the chapter.

Other approaches to coding a cookie function adjust the date and the path, as well as the key and value. Note that there is one space, following the semicolons in the string.

A fourth parameter for a cookie is a flag on whether the cookie is secure or not. A secure cookie can be requested only using SSL (HTTPS rather than HTTP).


Getting the cookie is not as easy because all cookies get concatenated into one string, separated by semicolons(;) on the cookie object. Following is an example of a cookie string:

var1=somevalue; var2=3.55; var3=true

I've seen several approaches used to get the keys. One uses the String split method to split on the semicolon; others use a variety of searches on substrings. The example function I've created uses a mix of both techniques:

function readCookie(key) {   var cookie = document.cookie;   var first = cookie.indexOf(key+"=");   // cookie exists   if (first >= 0) {     var str = cookie.substring(first,cookie.length);     var last = str.indexOf(";");     // if last cookie     if (last < 0) last = str.length;     // get cookie value     str = str.substring(0,last).split("=");     return unescape(str[1]);   } else {     return null;   } }

In the code, the key is concatenated to the equals sign (=), and the whole is searched in the string. When found, its first position gets a substring of the rest of the string. Within this new string, then, the semicolon is searched and if found, the string is either shortened to the semicolon or accessed as a whole (key is last item). Finally, the string is split on the equals sign to get the key and the value, separately. The return value is unescaped to return the original value.

To erase the cookie, eliminate its value (set to nothing), set the date to a past date, or both, as the following JS function demonstrates:

function eraseCookie (key) {    var cookieDate = new Date(2000,11,10,19,30,30);    document.cookie=key + "=; expires=" + cookieDate.toGMTString(  ) + "; path=/"; }

When the document cookie string is accessed next, the cookie will no longer exist.

Before any cookie functionality is used, it's best to first test to make sure cookies are implemented and enabled for the browser. It's not unusual for people to turn cookies off, and you'll want to account for this in your code. To check if cookies are enabled, use another built-in browser object, navigator, and the cookieEnabled property:

if (navigator.cookieEnabled) ...

Note that not all browsers return the correct value when testing the cookieEnabled property. For instance, IE 6.x does not set this property correctly. In these cases, there's little you can do other than set the cookie and see if you can find it.

Taking all of this together, Example 8-1 demonstrates an application that sets a value as a cookie that's accessed and incremented each time the page is loaded. When the value gets to 10, the cookie gets erased, and in the next iteration (page load), the cookie gets recreated.

Example 8-1. Setting, reading, and erasing cookies

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>Cookies</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript"> //<![CDATA[ // if cookie enabled if (navigator.cookieEnabled) {    var tst = new Array(  );    tst[0] = "hello"; tst[1]="there";    setCookie("doc",document);    alert(document.cookie);    var sum = readCookie("sum");    var iSum = 0;    if (sum) {       iSum = parseInt(sum) + 1;       alert(iSum);       if (iSum > 10) {          eraseCookie("sum");       } else {          setCookie("sum",iSum);       }    } else {       setCookie("sum", 0);    } } // set cookie expiration date in year 2010 function setCookie(key,value) {    var cookieDate = new Date(2010,11,10,19,30,30);    document.cookie=key + "=" + escape(value) + "; expires=" + cookieDate.toGMTString(  ) + "; path=/"; } // each cookie separated by semicolon; function readCookie(key) {   var cookie = document.cookie;   var first = cookie.indexOf(key+"=");   // cookie exists   if (first >= 0) {     var str = cookie.substring(first,cookie.length);     var last = str.indexOf(";");     // if last cookie     if (last < 0) last = str.length;     // get cookie value     str = str.substring(0,last).split("=");     return unescape(str[1]);   } else {     return null;   } } // set cookie date to the past to erase function eraseCookie (key) {    var cookieDate = new Date(2000,11,10,19,30,30);    document.cookie=key + "= ; expires="+cookieDate.toGMTString(  )+"; path=/"; } //]]> </script> </head> <body> </body> </html>

Cookies are handy little buggers, but one of their limitations is that a domain can store only 20 cookies, up to 4 KB in total size. For most cases, this is more than satisfactory; in fact, you should use even this smaller client-side storage sparingly. Still, there might be times when you want to store larger amounts of data.




Learning JavaScript
Learning JavaScript, 2nd Edition
ISBN: 0596521871
EAN: 2147483647
Year: 2006
Pages: 151

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net