Default Overwriting
By nature, when you write a cookie using "document.cookie" using the same name ([cookie_name] = cookie_data) as an existing cookie, the older cookie is overwritten by the newer one. Try the example below. Type in any text and click the "Set Cookie" link. This will set a cookie and then read it from your hard drive. Note that each entry you make overwrites the previous entry:
In most cases, the default of overwriting cookies with the same name is a blessing. It saves a lot of headaches and having to spend a lot of code detecting and killing cookies.
On the other hand, there are many situations where you might like to add data to an existing cookie. A simple JavaScript "shopping cart" would be an example. People would add data as they browsed and this information would be displayed and passed on to a CGI script on a final page. This requires adding to a cookie (or multiple cookies that we'll discuss in the next tutorial). The problem is that default overwriting would delete previous selections as new ones were made.
Appending Data To A Cookie
To add, or "append", data to a cookie we must first detect and read the old cookie already existing on the viewer's machine. We cannot directly add data to a cookie because of the default overwriting behavior.
We must read the old cookie, add new data to it to make a new cookie string containing both old and new data, and write this new string to the cookie.
Below is another text box that will keep adding your entries to your cookie. Type in one string and set the cookie. Now clear the box and type in another string. Notice how your string grows in the alert() box:
The JavaScript above follows a simple four step procedure for appending, or adding, data to cookies.
Step-By-Step
You append data to a cookie by following the DRAW technique:
Detect the old cookie. If one is not there, you generally start one.
Read the old cookie data into a variable. Don't bother "unescape()ing" it, it's just going to back on another cookie.
Add new data. Read and assign variables to new input. Now escape the new data and add it to the old (old_cookie + escape(new_data)).
Write the cookie. Put the string containing old and new data on the cookie using "document.cookie". This will overwrite the old cookie with both the old and new data. Note: The cookie's name will be automatically included in the "old_cookie" data.
Here's how to code the box above that appends data to a cookie. I called the function "test_cookie2()". First, we need to Detect any old cookies:
function cookie_test2(){
if (document.cookie && document.cookie != ""){
CODE TO ADD TO EXISTING COOKIE
}
else{
//start new cookie
var fresh_data = document.form2.box2.value;
document.cookie = "testcookie2=" + escape(fresh_data);
}
alert (unescape(document.cookie));
}//ends function
The above is the framework for the script. The IF checks for the existence of an old cookie. If one is found, we'll add more data to it in a minute. If no cookie is found, the ELSE statement makes one from the entered data. The alert() box reads and displays the "unescape()d" cookie data after the cookie has been written.
Now we need to Read the old cookie:
function cookie_test2(){
if (document.cookie && document.cookie != ""){
var old_cookie = document.cookie;
}
else{
//start new cookie
var fresh_data = document.form2.box2.value;
document.cookie = "testcookie2=" + escape(fresh_data);
}
alert (unescape(document.cookie));
}//ends function
The above reads any current cookie's data into a variable called "old_cookie". Now we need to read the new data:
function cookie_test2(){
if (document.cookie && document.cookie != ""){
var old_cookie = document.cookie;
var fresh_data = document.form2.box2.value;
}
else{
//start new cookie
fresh_data = document.form2.box2.value;
document.cookie = "testcookie2=" + escape(fresh_data);
}
alert (unescape(document.cookie));
}//ends function
For this simple cookie, I'm going to add the new data and write the cookie with the same line (document.cookie). More complex cookies are best compiled in a string variable and the cookie set on a separate "document.cookie" line:
function cookie_test2(){
if (document.cookie && document.cookie != ""){
var old_cookie = document.cookie;
var fresh_data = document.form2.box2.value;
document.cookie= old_cookie + escape(fresh_data);
}
else{
//start new cookie
fresh_data = document.form2.box2.value;
document.cookie = "testcookie2=" + escape(fresh_data);
}
alert (unescape(document.cookie));
}//ends function
Notice that we didn't have to "escape()" the "old_cookie" data. It was already "escape()ed" and we never "unescape()d" it. We only need to "escape()" the "fresh_data".
It's also important to remember that the cookie's name, "testcookie2=", is included in the "old_cookie" data. It is written when the cookie is originally created by the ELSE statement and hasn't been removed.
This brings up an important point when appending data to cookies: Don't process the old data any more than absolutely necessary. Normally you just need to assign a variable to "document.cookie" and leave it at that.
A More Complex Example
Now lets look at a more complex example. There are three input (form) pages in the example and a final page that collects the data from the three previous pages and displays it.
This is done by having each page add to a cookie. The first page sets the initial cookie and the other two add to it. This is done with the DRAW technique as above, but requires some advanced features.
When I have a project like this I start at the end - the display, or last, page. I code it so I'll know what I want displayed and decide on the variables needed and their names.
Once I decide on what variables and values I need, I decide what I want my cookie string to look like. In this case, I'll need to use some method of demarcation so I can break up the cookie string into the different values I need. Here's what I wanted my cookie string to look like (before "escape()"):
"growing_cookie=:::[name]:::[email address]:::[hair color]"
I didn't add an expiration date because one wasn't needed for the example. Notice the use of three colons (:::) to demarcate between the values and the cookie's name. These will be critical when breaking up the values with "split()" for the display.
By starting at the end and working backwards, such items like variable names and demarcation in the cookie string become apparent early on and don't have to be added in later. Your final results are the requirements and a good outline for your code, so it's a good idea to start at the final result and work backward.
After designing the cookie string, I made the form input pages. The first page checks for a cookie. In fact, it checks for the other cookies that were on this page and others you might have gotten from this site. If any cookies are detected, they are killed and a new cookie started. If no cookies are found, a new one is started.
The next two pages append data (DRAW) to the cookie. If no cookie was set on page 1, you are redirected to page one to start the cookie. The reason for this is that the data must be in order for the final display to work. Otherwise your email address might be presented as your hair color.
This type of strictly ordered format isn't always needed, but when it is, careful error control is required to keep everything flowing in the right order.
Pages 2 and 3 detect and read the old cookie and then add their data to the old string. Along with, and preceding the data, are three colons (:::) to demarcate the values. A typical appending string looks like this:
document.cookie = old_cookie + escape(":::" + address);
Again, I've done the appending and cookie writing on the same line. Notice that I only had to "escape()" the new data.
Now on the last page, the cookie will look just like the cookie string I designed at the start of the project. It's ready to be broken up with "split()" and have the values assigned to the variables for display.
There is a warning on the final page just in case you go back and add data. This creates too many values for the final display page. This is a simple example. In practice, you'd probably spend more effort analyzing the final cookie string.
View the source code of the example. The JavaScript is in the <head> of each page for easier viewing. Don't worry about the error control scheme or cookie killing. Just try to pick out how I followed the DRAW technique on each of the form pages to set and add to the cookie's data.
Debugging With Alert() Boxes
As you make your own version of the example, you'll need to keep up with what data is on your cookie from page to page. You can do this with well placed alert() boxes. These boxes can read and display your cookie's string: alert (unescape(document.cookie)).
I like using at least two in the early coding stages. One goes at the start of a page to show me the cookie data being received by the page. A second is coded right after the new cookie is written to make sure the new data has been properly appended.
When you start running into troubles anywhere in JavaScript, alert() boxes can really save the day. They can quickly display dynamic values at different points, like our cookie string, as they are being processed.
Summary & Exercises
To append new data onto an existing cookie follow the DRAW technique: Detect the old cookie. Read the old cookie into a variable and read new data into another variable(s). Add the new data to the old data with simple string combining (old_cookie + escape(new_data)). Any new data must be "escape()d", but old cookie data doesn't need to be because it already has been (or should have been) "escape()d".
The best way to troubleshoot your cookie string is to use strategically placed alert() boxes: alert (unescape(document.cookie)). This will tell you what's written on your cookie at the time of the alert(). I debugged the example by putting an alert box right before the redirect to the next page. That way I could see the final cookie going to the next page.
To start practicing appending to cookies, make a simple two-page example. The first page sets the cookie and the second reads it. Make a single text box, like the second text box on this page, that will let you keep adding text forever.
Next, make a version of the bigger example. You won't have to do all of the cookie killing I did unless you're setting as many cookies as a cookie tutorial site would. Remember to start at the final page, work backwards, and debug with alert() boxes.
Finally, make a multi-page form work with all of the JavaScript on an external .js file. Hint: Different pages need different code run outside of functions - before the page loads. You can't run all of the "outside of function" scripts on all of the pages. To get around this you can use if (window.location == "a_given_page.htm"){Code to run for that page}.
This would run only the specific start up statements for that page. Also, there's no reason to have to code cookie killing functions and error functions more than once.
The final exercise doesn't have much to do with cookies, but it's good practice for making more complex external JavaScripts. Most projects with any JavaScript at all will have these.
To Next Advanced JavaScript Lesson
Back To Advanced JavaScript Index
|