What is a cookie?
A cookie is a piece of data stored by a web browser on a user's hard disk.
Cookie storage is
rigidly controlled for security purposes, and the amount of data that can be stored
(which varies between browsers) is
small - typically 4K bytes per cookie, and 20 cookies per web domain (e.g. paulspages.co.uk).
Despite their limitations cookies are very useful, because they allow you to store data on a per-user basis. For example, instead of keeping a database of user names and preferences on your server, you can store each user's details on their own disk.
Disappearing cookies
Cookies are useful, but they're also unreliable. Some users set their
browsers not to accept cookies, and cookies can 'disappear' from a disk for a
variety of reasons, including space limitations or the user switching to a different browser. Cookies should never be used to store
irreplaceable data, and cookie-handling code should always be
defensive, i.e. able to handle situations where an expected cookie isn't found.
JavaScript and cookies
Using JavaScript, you can create and use cookies direct from web pages. This
is called 'client-side' cookie handling because the code runs in the browser,
or 'client', as opposed to server-side cookie handling, where code (e.g. cgi or
ASP) running on the web server sends cookie-handling instructions to the
browser. The code in the paulspages functions runs on Microsoft and Netscape
browsers from version 3.0 onwards, as well as other compatible browsers such as
Opera.
Why do I need these libraries?
JavaScript's built-in cookie-handling features are very basic. As you'll see
from the examples below, they leave it to you to extract individual cookies from
the document.cookie string, rely on you to convert data between escaped (special
character-encoded) and unescaped format, make setting expiry dates difficult,
and offer no support for space-saving multi-field cookies. Don't worry though,
because the paulspages.co.uk cookie-handling functions do all that for you!
What does a cookie look like?
A cookie is basically a text string consisting of a name and a value, like
this.
website=www.paulspages.co.uk
When a web page loads, the browser assembles all the cookies that are available to that page (see below) into a single string, called document.cookie. The cookies are separated by semicolons (;). Here's an example:
website=www.paulspages.co.uk; name=Paul Stephens; location=Bath, UK
The document.cookie string may include cookies written by other pages in your website. You don't get any choice about which cookies appear in document.cookie - the browser just sends you everything.
Extracting individual cookies
In basic JavaScript it's up to you to extract individual cookies from document.cookie, and to handle any problems caused by values containing = or ; characters
(e.g. "location=Bath; UK"). In practice the latter means using the
escape() function to convert any special characters to "escape
sequences" before writing a cookie, so the actual data stored is something
like this:
location=Bath%2C%20UK
where %2C is the 'escaped' code for a comma, and %20 the code for a space. When you read the cookie back, you use the unescape() function to convert the escape sequences back to characters.
Access paths
Web pages can "see" cookies created by other pages, but only within
strict rules enforced by the browser. The main rule is that a page will only see
cookies written by pages from the same server domain (e.g. paulspages.co.uk).
Furthermore, a page will only see cookies written by pages from the same or higher-level folders within its domain. For example, if your server has this folder structure:
/ (root folder) index.htm | |---------------------| /news /reviews newspage1.htm reviewpage1.htm newspage2.htm | |---- /news/newsflash newsflash1.htmBy default, the page newspage1.htm will see cookies written by itself, index.htm and newspage2.htm, but not those written by reviewpage1.htm or newsflash1.htm. Reviewpage1, meanwhile, will see only cookies written by itself and index.htm.
You can override this by setting an access path when writing a cookie (see "Writing cookies", below, for details of how to do this).
In this example, giving a cookie from newsflash1.htm an access path of "/news" would enable newspage1.htm and newspage2.htm to see it. Setting an access path of "/" (root folder) makes a cookie available to all pages in your domain.
Name clashes avoided
The access rules prevent pages from snooping on cookies written by
other websites, and also avoid cookie name clashes. This means that you can create a cookie
named "location" without worrying whether a page from another website
has created one with the same name, because only your site's 'location' cookie will be supplied to your pages. The folder rules do the same thing
within your website - unless, of course, you give all your cookies an access
path of "/".
Note that there's no way of telling which folder or page an existing cookie has come from, or what its access path is, unless the page that created it included these details as part of its data value.
Sub-domains
Some websites use sub-domains, for example news.mydomain.com and
reviews.mydomain.com. By default these count as separate domains, so a cookie
from one sub-domain can't be seen by pages from another. However you can
override this by specifying a domain for the cookie. (see "Writing cookies",
below, for details of how to do this).
For example, setting a domain of mydomain.com would cause pages from news.mydomain.com and reviews.mydomain.com to see the cookie.
You can set a path and a domain for a cookie.
Cookie expiry
Cookies are designed to have temporary lifespans. By default, this is just
the current browser session; when the user unloads the browser, the cookie is
deleted from their disk.
Alternatively you can set an expiry date when you create a cookie (see "Writing cookies" for details). The browser will then attempt to keep the cookie on disk until that date. However the cookie may be deleted before then for a number of possible reasons (for example because the cookie storage limit has been reached), so remember - always program defensively to handle "missing" cookies!
To delete an existing cookie, you write it with an expiry date earlier than the present date.
Note that there's no way of telling an existing cookie's expiry date, unless the page that created it included this information as part of its data value.
Writing cookies
In most respects JavaScript is a very consistent language, but not when it comes
to cookie handling.
When you read the document.cookie string (e.g. myCookies = document.cookie), it consists of name=value pairs for all the cookies available to the page, as described above. However, when you write to it (e.g. document.cookie = myCookieData) it behaves completely differently.
(NOTE - the details below are included for information only - the cookie-handling libraries take care of writing cookies for you).
When you write to document.cookie, the browser expects just a single cookie's name=value pair. This will be used to either create a new cookie, or update an existing one if the name already exists. Never include the name=value pairs for the other cookies that were in the original document.cookie string - doing this is likely to create spurious cookies with the "wrong" expiry dates and access paths.
Here's the code to add a cookie:
document.cookie = "location=" + escape("Bath, UK")
As well as the name=value pair, you can add extra pairs to control the path and expiry date (see above).
You add a path like this:
document.cookie = "location=" + escape("Bath, UK") + "; path=/news"
In this example, the actual value written to document.cookie would be
location=Bath%2C%20UK; path=/news
Expiry dates need to be expressed as string values, like this:
document.cookie = "location=" + escape("Bath,
UK") + "; path=/" +
"; expires=" + myDateObj.toGMTString()
where myDateObj is a JavaScript Date() object, set to the date on which you want the cookie to expire.
You add a domain like this:
document.cookie = "location=" + escape("Bath,
UK") + "; path=/"
+ "; expires=" + myDateObj.toGMTString() + "; domain=mydomain.com"
What do the paulspages.co.uk cookie functions do?
The cookie functions take the hard work out of handling cookies from
JavaScript. They:
Multi-field cookies
Strictly speaking there's no such thing as a multi-field (or multi-value)
cookie; each cookie contains one data value, so if you want to store a user's
website, name and location, you need three cookies, as shown above.
You can, however, make your own multi-field cookie by concatenating (assembling) its fields into a single string, which becomes the cookie's data value. For example, instead of having three separate cookies ("website", "name" and "location"), you could have one named "userdetails", with three fields. Here's an example:
userdetails=www.paulspages.co.uk#Paul%20Stephens#Bath%2C%20UK
Note the # characters, used as field delimiters (separators). When you read the cookie into a page, you split the data into separate variables or array elements by finding the # characters.
Multi-field cookies save space (by not having a separate name for each data value), use up fewer of the 20 cookies per domain allowed by some browsers, and make programming easier, since you only have to read and write one cookie.
The object-based www.paulspages.co.uk cookie functions support multi-field cookies automatically. Each cookie object you create contains an array, named fields[]. You can add as many elements as you like to this array, and when you write the cookie to disk, the cookie object concatenates them into a single string, inserting the fields delimeters automatically. When you read the cookie into a page, the object splits the string back into elements of its fields[] array.