In the preceding example, we used document.cookie to retrieve a string containing information about the cookies that have been set. However, this string has two limitations.
First, the cookies are retrieved in name/value pairs, with each individual cookie separated by a semicolon. The expires, path, domain, and secure parts of the cookie are not available to us and cannot be retrieved.
Second, the cookie property allows you to retrieve only all the cookies set for a particular path and, when hosted on a web server, that web server. So, for example, there's no simple way of just getting the value of a cookie with the name Age. To do this we'll have to use the string manipulation techniques we've learned in previous chapters to cut the information we want out of the returned string.
A lot of different ways exist to get the value of an individual cookie, but the way we'll use has the advantage of working with all cookie-enabled browsers. We use the following function:
function getCookieValue(cookieName) { var cookieValue = document.cookie; var cookieStartsAt = cookieValue.indexOf(" " + cookieName + "="); if (cookieStartsAt == -1) { cookieStartsAt = cookieValue.indexOf(cookieName + "="); } if (cookieStartsAt == -1) { cookieValue = null; } else { cookieStartsAt = cookieValue.indexOf("=", cookieStartsAt) + 1; var cookieEndsAt = cookieValue.indexOf(";", cookieStartsAt); if (cookieEndsAt == -1) { cookieEndsAt = cookieValue.length; } cookieValue = unescape(cookieValue.substring(cookieStartsAt, cookieEndsAt)); } return cookieValue; }
The first task of the function is to get the document.cookie string and store it in the variable cookieValue.
var cookieValue = document.cookie;
Next we need to find out where the cookie with the name passed as a parameter to the function is within the cookieValue string. We use the indexOf() method of the String object to find this information, as shown in the following line.
var cookieStartsAt = cookieValue.indexOf(" " + cookieName + "=");
The method will either return the character position where the individual cookie is found or -1 if no such name, and therefore no such cookie, exists. We search on " " + cookieName + "=" so that we don't inadvertently find cookie names or values containing the name that we require. For example, if we have xFoo, Foo, and yFoo as cookie names, a search for Foo without a space in front would match the xFoo first, which is not what we want!
If cookieStartsAt is -1, the cookie does not exist or it's at the very beginning of the cookie string so there is no space in front of the cookie name. To see which of these is true, we do another search, this time with no space.
if (cookieStartsAt == -1) { cookieStartsAt = cookieValue.indexOf(cookieName + "="); }
In the next if statement we check to see whether the cookie has been found. If it hasn't, we set the cookieValue variable to null.
if (cookieStartsAt == -1) { cookieValue = null; }
If the cookie has been found, we get the value of the cookie we want from the document.cookie string in an else statement. We do this by finding the start and the end of the value part of that cookie. The start will be immediately after the equals sign following the name. So in the following line, we find the equals sign following the name of the cookie in the string by starting the indexOf() search for an equals sign from the character at which the cookie name/value pair starts.
else { cookieStartsAt = cookieValue.indexOf("=", cookieStartsAt) + 1;
We then add one to this value to move past the equals sign.
The end of the cookie value will either be at the next semicolon or at the end of the string, whichever comes first. We do a search for a semicolon, starting from the cookieStartsAt index in the next line.
var cookieEndsAt = cookieValue.indexOf(";", cookieStartsAt);
If the cookie we are after is the last one in the string, there will be no semicolon and the cookieEndsAt variable will be –1 for no match. In this case we know the end of the cookie value must be the end of the string, so we set the variable cookieEndsAt to the length of the string.
if (cookieEndsAt == -1) { cookieEndsAt = cookieValue.length; }
We then get the cookie's value using the substring() method to cut the value that we want out of the main string. Because we have encoded the string with the escape() function, we need to unescape it to get the real value, hence the use of the unescape() function.
cookieValue = unescape(cookieValue.substring(cookieStartsAt, cookieEndsAt)); }
Finally we return the value of the cookie to the calling function.
return cookieValue;
Now we know how to create and retrieve cookies. Let's use this knowledge in an example where we check to see if any changes have been made to a website since the user last visited it.
We'll be creating two pages for this example. The first is the main page for a website; the second is the page with details of new additions and changes to the website. A link to the second page will only appear on the first page if the user has visited the page before (that is, a cookie exists) but has not visited since the page was last updated.
<!DOCTYPE html PUBLIC "-//W3C//DTD html 4.01 Transitional//EN"> <html> <head> <title>Cookie Example</title> <script language=JavaScript type="text/javascript"> var lastUpdated = new Date("Tue, 28 Dec 2010"); function getCookieValue(cookieName) { var cookieValue = document.cookie; var cookieStartsAt = cookieValue.indexOf(" " + cookieName + "="); if (cookieStartsAt == -1) { cookieStartsAt = cookieValue.indexOf(cookieName + "="); } if (cookieStartsAt == -1) { cookieValue = null; } else { cookieStartsAt = cookieValue.indexOf("=", cookieStartsAt) + 1; var cookieEndsAt = cookieValue.indexOf(";", cookieStartsAt); if (cookieEndsAt == -1) { cookieEndsAt = cookieValue.length; } cookieValue = unescape(cookieValue.substring(cookieStartsAt, cookieEndsAt)); } return cookieValue; } function setCookie(cookieName, cookieValue, cookiePath, cookieExpires) { cookieValue = escape(cookieValue); if (cookieExpires == "") { var nowDate = new Date(); nowDate.setMonth(nowDate.getMonth() + 6); cookieExpires = nowDate.toGMTString(); } if (cookiePath != "") { cookiePath = ";Path=" + cookiePath; } document.cookie = cookieName + "=" + cookieValue + ";expires=" + cookieExpires + cookiePath; } </script> </head> <body> <h2 align=center>Welcome to my website</h2> <br><br> <center> <script> var lastVisit = getCookieValue("LastVisit"); if (lastVisit != null) { lastVisit = new Date(lastVisit); if (lastVisit < lastUpdated) { document.write("<A href=\"WhatsNew.htm\">"); document.write("<img src=\"WhatsNew.gif\" border=0></A>"); } } var nowDate = new Date(); setCookie("LastVisit", nowDate.toGMTString(),"","") </script> </center> </body> </html>
This page needs to be saved as MainPage.htm. Note that it contains the two functions, setCookie() and getCookieValue(), that we created earlier. Also note that the image WhatsNew.gif is referenced by this page; either create such an image, or retrieve the image from the code download.
Next, we'll just create a simple page to link to for the What's New details.
<html> <body> <h2 align=center>Here's what's new on this website</h2> </body> </html>
Save this page as WhatsNew.htm.
Load MainPage.htm into a browser. The first time we go to the main page, there will be just a heading saying "Welcome to my website". Obviously if this were a real website, it would have a bit more than that, but it suffices for our example. However, refresh the page and suddenly we'll see the page shown in Figure 11-15.
If we click on the image, we're taken to the WhatsNew.htm page detailing all the things added to the website since we last visited. Obviously nothing has actually changed in our example website between us loading in the page and then refreshing it. We got around this for testing purposes by setting the date when the website last changed, stored in variable lastUpdated, to a date in the future (here, December 28, 2010).
The WhatsNew.htm page is just a simple html page with no script, so we will confine our attention to MainPage.htm. In the head of the page in the first script block, we declare the variable lastUpdated.
var lastUpdated = new Date("Tue, 28 Dec 2010");
Whenever we make a change to the website this variable needs to be changed. It's currently set to Tue, 28 Dec 2010 just to make sure we see a "What's New" image when we refresh the page. A better alternative for live pages would be the document.lastModified property, which returns the date the page was last changed.
The rest of the first script block contains the two functions getCookieValue() and setCookie() that we looked at earlier. These haven't changed, so we won't discuss them in detail here.
The interesting material is in the second script block that is found within the body of the page. First we get the date of the user's last visit stored in the LastVisit cookie using the getCookieValue() function.
var lastVisit = getCookieValue("LastVisit");
If it's null, the user has never been here before, or it has been six or more months since the last visit, and the cookie has expired. Either way, we won't put a "What's New" image up because everything is new if the user is a first time visitor, or a lot has probably changed in the last six months—more than what our What's New page will detail.
If lastVisit is not null, we need to check whether the user visited the site before the site was last updated, and if so direct the user to a page that shows what is new. We do this within the if statement.
if (lastVisit != null) { lastVisit = new Date(lastVisit); if (lastVisit < lastUpdated) { document.write("<A href=\"WhatsNew.htm\">"); document.write("<img src=\"WhatsNew.gif\" border=0></A>"); } }
We first create a new Date object based on the value of lastVisit and store that back into the lastVisit variable. Then, in the condition of the inner if statement, we compare the date of the user's last visit with the date we last updated the website. If things have changed since the user's last visit, we write the What's New image to the page, so the user can click it and find out what's new. Note that we have used the escape character \" for the " inside the strings that are written to the page because, otherwise, JavaScript will think they indicate the end of the string.
Finally, at the end of the script block, we reset the LastVisit cookie to today's date and time using the setCookie() function.
var nowDate = new Date(); setCookie("LastVisit", nowDate.toGMTString(),"","")