Section G. Cookies


G. Cookies

HTTP is a stateless protocol. This means that a Web server doesn't remember anything. If a user requests a page, the server has no idea if it is a new user, a user who visits the site several times a week, or a user who has been obsessively reloading every single page on the site for the past few hours. The server just sends the requested page and forgets about it.

Usually this is a good thing. Since it doesn't have any memory, a Web server can fully concentrate on serving Web pages, instead of also having to do tedious and time-consuming administration. HTTP was deliberately designed this way.

Nonetheless, sometimes you need to remember things about your visitors. Is this user logged in? Has this user requested the larger font size? Has this user already voted on the poll? To enable you to do this, Netscape introduced cookies back in the Internet's gray antiquity.

Cookies are small text files that are stored on the user's computer. They are related to certain directories in a certain Web domain, and when the user's browser requests a page from these directories, the cookies are automatically sent with the HTTP request. It's up to the server to do something with the information the cookies carry.

You can also set and retrieve cookies in JavaScript, and I do so in Edit Style Sheet and Site Survey. In both cases I want to remember certain information. In Edit Style Sheet I want to know which CSS selector the user was editing the last time he visited the page, so that I can automatically set the form to this selector, and the user can continue where he left off.

In Site Survey I want to know if the user has been selected for the survey or not. If a user comes to a page containing Site Survey for the first time, the script randomly determines whether or not the user is selected for the survey. If he is, the script makes sure that the popup appears in the way we've discussed in 6B.

name/value

The actual information of a cookie is contained in a name/value pair. The name is what makes a cookie unique for a given path: if you set a new cookie with the same name, the old cookie is overwritten.

In Site Survey, the name/value pair is "ST_status=yes" if the user is selected for the survey, or "ST_status=no" if he isn't selected.

Every subsequent time the user loads a page that contains Site Survey, the cookie is present, and the script uses the information contained in it to decide what to do next.

Expiry date

Cookies have an expiry date after which they are no longer associated with the site and are lost. If you don't define an expiry date, the cookie is lost when the current browser session ends; i.e., when the user closes his browser. If you define an expiry date in the past, the cookie is removed immediately.

Expiry dates are set for GMT (Greenwich time) in the following format:

Tue, 23 Jan 2007 13:57:39 UTC 


It's in this expiry date that the Site Survey "yes" and "no" cookies differ. If the user has been selected for the survey, the script sets the expiry date to the end of the survey period, so that the user is never bothered again. If he hasn't been selected, on the other hand, the script sets the expiry date to one day after the cookie was set.

I did this deliberately. The client and I agreed that if a user not already selected for the survey visits the site at least one day later, he is once again eligible for selection. In order to do this, the "no" cookie has to be removed after a day; i.e., its expiry date has to be set to one day after it was created.

domain and path

You can set cookies only for your site's domain, and by default they're only set for the path (usually the directory) of the page that sets them.

For instance, on www.quirksmode.org/js/cookies.html I set a few test cookies to help my readers understand them. If I did nothing, these cookies would only be associated with pages in www.quirksmode.org/js/ and its subdirectories.

Usually this is too restrictive. In general you want to associate your cookies with all pages on your site. All cookies have a path that contains the directory path they're associated with. If I set path=/, all cookies are associated with the Web root of the server and all its subdirectoriesin other words, the entire site. This is usually what you want.

You can't associate cookies with another domain. For example, since I set my test cookies in the domain www.quirksmode.org, they cannot be associated with, say, www.google.com or www.microsoft.com: only Google and Microsoft are allowed to set cookies for their domains. This is a security feature.

Subdomains, however, are another matter. Suppose I had a domain search.quirksmode.org. Since my test cookies are set in the domain www.quirksmode.org, the pages in search.quirksmode.org do not have access to those cookies. I can change this by setting the cookie's domain. If I make it domain=quirksmode.org, the cookie would be associated with all pages in all subdomains of quirksmode.org, including www and search.

Setting a cookie

To summarize, a cookie consists of the following parts:

  • A name/value pair that contains the actual information; this is empty by default.

  • A GMT string with the expiry date; if not set, the cookie will expire when the user closes his browser.

  • A directory path; by default the directory of the page the cookie is set to on.

  • A domain; by default the domain of the page the cookie is set to on.

The syntax is as follows:

document.cookie = 'testcookie=yes; expires=Tue, 23 Jan 2007 13:57:39 UTC; path=/; domain=quirksmode.org'; 


This creates a new cookie with the name testcookie and the value yes, valid until 23 January 2007 in all directories of quirksmode.org and all its subdomains.

This syntax is very precise; note the semicolons and spaces that separate the various arguments and the strict form of the expiry date.

Once set, the cookie is immediately available for reading. When the user next requests a page from your site, the cookie is sent along in the HTTP headers and can be caught by server-side programs.

Cookie Restrictions

Web browsers are not required to store more than 300 cookies. In addition, they are not required to store more than 20 cookies per domain. Finally, no cookie name/value pair may be larger than 4K.

I haven't personally tested the presence or absence of these restrictions in the various browsers, but in general you should assume that all browsers obey them.


document.cookie

The cookie is stored in document.cookie. This is a rather odd property that partially behaves as a string, but is not a string. You set a cookie by assigning it to document.cookie. If you read this property, though, it contains the name/value pairs of all cookies associated with the current page.

For instance:

document.cookie = 'testcookie=yes; expires=Tue, 23 Jan 2007 13:57:39 UTC; path=/; domain=quirksmode.org'; document.cookie = 'testcookie2=maybe; expires=Tue, 23 Jan 2007 13:57:39 UTC; path=/; domain=quirksmode.org'; alert(document.cookie); 


Now the alert says "testcookie=yes;testcookie2=maybe".

Reading cookies

To read out a previously set cookie, you should take document.cookie and split it by semicolons. This gives you the name/value pairs of all cookies associated with the current page, and you can search them for the name of the cookie you're looking for.

For instance:

var searchString = 'testcookie'; // we're looking for this name var cookieValue = ''; var cookies = document.cookie.split(';'); for (var i=0;i<cookies.length;i++) {    if (cookies[i].indexOf(searchString + '=') == 0)            // if name/value starts with the name we want    {            cookieValue = cookies[i].substring(cookies.[i].indexOf('=')+1);    } } 


Deleting cookies

You delete a cookie by creating a new cookie with the same name but with an expiry date in the past. For instance:

document.cookie = 'testcookie=yes; expires=Thu, 23 Jan 2003 14:32:04 GMT; path=/; domain=quirksmode.org'; 


Now the test cookie is removed, since its expiry date lies in the past.

My Cookie Functions

The syntax of all these actions is rather precise. Therefore I always use three helper functions to create, read, and erase cookies. They occur in Site Survey and Edit Style Sheets. See http://www.quirksmode.org/js/cookies.html for a line-by-line explanation of these functions.


Example cookie use

In Site Survey I use cookies as follows (I left out a few lines of code):

[Site Survey/survey.js, lines 33-58, condensed]

function ST_init() {    var currentStatus = readCookie('ST_status');    if (currentStatus == 'no') return;    ST_loaded = true;    addEvent(window,"unload",ST_exit);    if (currentStatus == 'yes') return;    var ST_selectedForSurvey = (Math.random()*ST_sample < 1)    if (!ST_selectedForSurvey){            createCookie('ST_status','no',1);            return; }    createCookie('ST_status','yes',ST_surveyPeriod);    addEvent(document,"click",ST_openPopup); } 


When the page is initialized, I read out the ST_status cookie to find out if the user has already visited the page and, if so, whether she was selected for the survey. If not (currentStatus == 'no'), I immediately end the function: nothing should happen.

If the user has been selected for the survey, or if it's her first visit, I set ST_loaded to true and set an onunload event handler to fire the function that stores the name of the current page in the popup window. We discussed both features in 6B.

If the user has already been selected for the survey (currentStatus == 'yes'), I end the function: we've done enough.

If it's the user's first visit, I now draw a random number to decide whether she is selected for the survey. If not, I set the ST_status cookie to 'no': user not selected. This cookie expires in one day; if the user returns after that time, she's again eligible for the survey. Then I end the function.

If the user is selected, I set the ST_status cookie to 'yes'. This cookie expires only at the end of the survey period; once a user has been selected, she gets the popup exactly once (on this page). Finally, I add an onclick event handler to the entire document, so that if the user clicks anywhere in the document, the popup is opened.

User control

Modern browsers allow users to manage their cookie permissions. They can choose never to accept any cookies, or not to accept third-party cookies, (meaning, they can choose to allow cookies only from the domain they're visiting.) In addition, all browsers allow the user to see and remove all currently active cookies. Because of these restrictions, you can never be 100% certain that a cookie-based system will work in all circumstances.

Don't Take Cookies from Strangers

Third-party cookies are usually set by banner farms. If a site owner decides to add banners to his site, he adds a bit of (badly written) JavaScript code that imports an image, a Flash movie, or another file. Now the page also requests files from the banner farm's server, and therefore this server, too, is allowed to set cookies in the user's browser. Banner farmers love these cookies, because they allow the farmers to follow individual users over the entire Internet: whenever a user comes to a site that uses the same banner service, this fact is registered by the banner farm's server.

Since this clearly violates the privacy of Internet users, modern browsers refuse these third-party cookies by default.


Determining cookie support

With all that in mind, how do you find out if a browser supports cookies? Modern browsers all have a navigator.cookieEnabled property that is true if they support cookies. So you can do the following:

if (navigator.cookieEnabled) {    // cookies enabled; set or read them } 


Frankly, I discovered this useful property only while doing research for this book. Therefore, Site Survey contains an old-style cookie detection that's also suited for older browsers. I set a test cookie and try to read it. If I can't, the browser doesn't support cookies:

[Site Survey/survey.js, lines 10-16]

var ST_cookiesSupported = false; createCookie('ST_test','supported',1); if (readCookie('ST_test')) {     ST_cookiesSupported = true;     eraseCookie('ST_test'); } 


First I set ST_cookiesSupported to false. Then I create a test cookie and try to read it. If that's possible, I set ST_cookiesSupported to true and erase the cookie. I use ST_cookiesSupported in ST_init:

[Site Survey/survey.js, lines 33-35, condensed]

function ST_init() {    if (!ST_cookiesSupported) return; 


If it's still false, cookies are not supported, and the function ends immediately.



ppk on JavaScript. Modern, Accessible, Unobtrusive JavaScript Explained by Means of Eight Real-World Example Scripts2006
ppk on JavaScript. Modern, Accessible, Unobtrusive JavaScript Explained by Means of Eight Real-World Example Scripts2006
ISBN: N/A
EAN: N/A
Year: 2005
Pages: 116

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