19.4. Cookie Example We end this discussion of cookies with a useful utility for working with cookies, shown a little later in Example 19-2. The Cookie( ) constructor reads the value of a named cookie. The store( ) method of a cookie stores data in that cookie, using the lifetime, path, and domain you specify, and the remove( ) method of a cookie deletes the cookie by setting its max-age attribute to 0. The Cookie class defined in this example stores the names and values of multiple state variables in a single cookie. To associate data with a cookie, simply set properties of the Cookie object. When you call the store( ) method on the cookie, the names and values of the properties you have added to the object become the cookie value that is saved. Similarly, when you create a new Cookie object, the Cookie( ) constructor looks for an existing cookie with the name you have specified. If it finds it, it parses its value as a set of name/value pairs and sets them as properties of the newly created Cookie object. To help you understand Example 19-2, Example 19-1 begins with a simple web page that uses the Cookie class. Example 19-1. Using the Cookie class <script src="/books/2/427/1/html/2/Cookie.js"></scripty><!-- include the cookie class --> <script> // Create the cookie we'll use to save state for this web page. var cookie = new Cookie("vistordata"); // First, try to read data stored in the cookie. If the cookie doesn't // exist yet (or doesn't have the data we expect), query the user if (!cookie.name || !cookie.color) { cookie.name = prompt("What is your name:", ""); cookie.color = prompt("What is your favorite color:", ""); } // Keep track of how many times this user has visited the page if (!cookie.visits) cookie.visits = 1; else cookie.visits++; // Store the cookie data, which includes the updated visit count. We set // the cookie lifetime to 10 days. Since we don't specify a path, this // cookie will be accessible to all web pages in the same directory as this // one or "below" it. We should be sure, therefore, that the cookie // name, "visitordata" is unique among these pages. cookie.store(10); // Now we can use the data we obtained from the cookie (or from the // user) to greet a user by name and in her favorite color. document.write('<h1 style="color:' + cookie.color + '">' + 'Welcome, ' + cookie.name + '!' + '</h1>' + '<p>You have visited ' + cookie.visits + ' times.' + '<button onclick="window.cookie.remove( );">Forget Me</button>;'); </script> | The Cookie class itself is listed in Example 19-2. Example 19-2. A Cookie utility class /** * This is the Cookie( ) constructor function. * * This constructor looks for a cookie with the specified name for the * current document. If one exists, it parses its value into a set of * name/value pairs and stores those values as properties of the newly created * object. * * To store new data in the cookie, simply set properties of the Cookie * object. Avoid properties named "store" and "remove", since these are * reserved as method names. * * To save cookie data in the web browser's local store, call store( ). * To remove cookie data from the browser's store, call remove( ). * * The static method Cookie.enabled( ) returns true if cookies are * enabled and returns false otherwise. */ function Cookie(name) { this.$name = name; // Remember the name of this cookie // First, get a list of all cookies that pertain to this document. // We do this by reading the magic Document.cookie property. // If there are no cookies, we don't have anything to do. var allcookies = document.cookie; if (allcookies == "") return; // Break the string of all cookies into individual cookie strings // Then loop through the cookie strings, looking for our name var cookies = allcookies.split(';'); var cookie = null; for(var i = 0; i < cookies.length; i++) { // Does this cookie string begin with the name we want? if (cookies[i].substring(0, name.length+1) == (name + "=")) { cookie = cookies[i]; break; } } // If we didn't find a matching cookie, quit now if (cookie == null) return; // The cookie value is the part after the equals sign var cookieval = cookie.substring(name.length+1); // Now that we've extracted the value of the named cookie, we // must break that value down into individual state variable // names and values. The name/value pairs are separated from each // other by ampersands, and the individual names and values are // separated from each other by colons. We use the split( ) method // to parse everything. var a = cookieval.split('&'); // Break it into an array of name/value pairs for(var i=0; i < a.length; i++) // Break each pair into an array a[i] = a[i].split(':'); // Now that we've parsed the cookie value, set all the names and values // as properties of this Cookie object. Note that we decode // the property value because the store( ) method encodes it. for(var i = 0; i < a.length; i++) { this[a[i][0]] = decodeURIComponent(a[i][1]); } } /** * This function is the store( ) method of the Cookie object. * * Arguments: * * daysToLive: the lifetime of the cookie, in days. If you set this * to zero, the cookie will be deleted. If you set it to null, or * omit this argument, the cookie will be a session cookie and will * not be retained when the browser exits. This argument is used to * set the max-age attribute of the cookie. * path: the value of the path attribute of the cookie * domain: the value of the domain attribute of the cookie * secure: if true, the secure attribute of the cookie will be set */ Cookie.prototype.store = function(daysToLive, path, domain, secure) { // First, loop through the properties of the Cookie object and // put together the value of the cookie. Since cookies use the // equals sign and semicolons as separators, we'll use colons // and ampersands for the individual state variables we store // within a single cookie value. Note that we encode the value // of each property in case it contains punctuation or other // illegal characters. var cookieval = ""; for(var prop in this) { // Ignore properties with names that begin with '$' and also methods if ((prop.charAt(0) == '$') || ((typeof this[prop]) == 'function')) continue; if (cookieval != "") cookieval += '&'; cookieval += prop + ':' + encodeURIComponent(this[prop]); } // Now that we have the value of the cookie, put together the // complete cookie string, which includes the name and the various // attributes specified when the Cookie object was created var cookie = this.$name + '=' + cookieval; if (daysToLive || daysToLive == 0) { cookie += "; max-age=" + (daysToLive*24*60*60); } if (path) cookie += "; path=" + path; if (domain) cookie += "; domain=" + domain; if (secure) cookie += "; secure"; // Now store the cookie by setting the magic Document.cookie property document.cookie = cookie; } /** * This function is the remove( ) method of the Cookie object; it deletes the * properties of the object and removes the cookie from the browser's * local store. * * The arguments to this function are all optional, but to remove a cookie * you must pass the same values you passed to store( ). */ Cookie.prototype.remove = function(path, domain, secure) { // Delete the properties of the cookie for(var prop in this) { if (prop.charAt(0) != '$' && typeof this[prop] != 'function') delete this[prop]; } // Then, store the cookie with a lifetime of 0 this.store(0, path, domain, secure); } /** * This static method attempts to determine whether cookies are enabled. * It returns true if they appear to be enabled and false otherwise. * A return value of true does not guarantee that cookies actually persist. * Nonpersistent session cookies may still work even if this method * returns false. */ Cookie.enabled = function( ) { // Use navigator.cookieEnabled if this browser defines it if (navigator.cookieEnabled != undefined) return navigator.cookieEnabled; // If we've already cached a value, use that value if (Cookie.enabled.cache != undefined) return Cookie.enabled.cache; // Otherwise, create a test cookie with a lifetime document.cookie = "testcookie=test; max-age=10000"; // Set cookie // Now see if that cookie was saved var cookies = document.cookie; if (cookies.indexOf("testcookie=test") == -1) { // The cookie was not saved return Cookie.enabled.cache = false; } else { // Cookie was saved, so we've got to delete it before returning document.cookie = "testcookie=test; max-age=0"; // Delete cookie return Cookie.enabled.cache = true; } } | |