<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:atom="http://www.w3.org/2005/Atom"
    xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
    xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
    >

<channel>
    <title>Webmonkey &#187; cookies</title>
    <atom:link href="http://www.webmonkey.com/tag/cookies/feed/" rel="self" type="application/rss+xml" />
    <link>http://www.webmonkey.com</link>
    <description>The Web Developer&#039;s Resource</description>
    <lastBuildDate>Mon, 06 May 2013 17:29:19 +0000</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <generator>http://wordpress.org/?v=3.4.2</generator>
    
    <item>
        <title>Advanced JavaScript Tutorial &#8211; Lesson 2</title>
        <link>http://www.webmonkey.com/2010/02/advanced_javascript_tutorial_-_lesson_2/</link>
        <comments>http://www.webmonkey.com/2010/02/advanced_javascript_tutorial_-_lesson_2/#comments</comments>
        <pubDate>Tue, 16 Feb 2010 01:45:47 +0000</pubDate>

                <dc:creator>Webmonkey Staff</dc:creator>

        <guid isPermaLink="false">http://stag.wired.com/primate/?p=721</guid>
        		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[cookies]]></category>
		<category><![CDATA[thau]]></category>
		<category><![CDATA[wiki]]></category>
        <description><![CDATA[Welcome back. Now that your brain has re-acclimated to the semicolons and curly braces of the JavaScript world, it&#8217;s time to learn something useful and exciting. We&#8217;ll spend this lesson sampling those tasty treats known as cookies &#8211; the little bits of information you can leave on the computers of people who visit your site. [...]]]></description>

            <content:encoded><![CDATA[<!-- wpautop disabled --><p>Welcome back. Now that your brain has re-acclimated to the semicolons and curly braces of the JavaScript world, it&#8217;s time to learn something useful and exciting.

</p><p>We&#8217;ll spend this lesson sampling those tasty treats known as cookies &#8211; the little bits of information you can leave on the computers of people who visit your site. Cookies allow you to give your pages a personal touch. For instance, with a cookie you can &#8220;remember&#8221; people&#8217;s names and serve up a warm greeting every time they re-visit. You can also remember user preferences &#8211; if a visitor generally comes in on a slow connection, a cookie lets you know to automatically serve them minimal graphics.</p>
<br />
<span id="more-721"></span>
<p>Cookies can be very useful — and sometimes scary:When I buy airplane tickets online, the service I use remembers not only my name, but also where I live and my seating preferences. It even knows who I traveled with last and asks if that person will be joining me on my next flight. There&#8217;s a fine line between useful and invasive.

</p><p>As long as you use them responsibly and effectively (and don&#8217;t freak anyone out with Big Brother knowledge), cookies can be extremely handy for all sorts of reasons. So I&#8217;m going to show you how they work. But before we get our hands all doughy, we should cover two JavaScript topics:fancy string handling and associative arrays.

</p>

<table id="toc" class="toc" summary="Contents"><tbody><tr><td><div id="toctitle"><h2>Contents</h2> </div>



<ol>

<li><a href="#Fancy_String_Handling">Fancy String Handling</a></li>

<li><a href="#indexOf">indexOf</a></li>

<li><a href="#charAt">charAt</a></li>

<li><a href="#String_Exercise_1">String Exercise 1</a>



<ol>

<li><a href="#Substring">Substring</a></li>

<li><a href="#The_Split_Method">The Split Method</a></li>

<li><a href="#Associative_Arrays">Associative Arrays</a></li>

<li><a href="#Example_of_an_Associative_Array">Example of an Associative Array</a></li>



<li><a href="#Cookie_Introduction">Cookie Introduction</a></li>

<li><a href="#More_About_Cookies">More About Cookies</a></li>

</ol>

</li>

<li><a href="#Setting_Cookies">Setting Cookies</a>

<ol>

<li><a href="#Reading_Cookies">Reading Cookies</a></li>



</ol>

</li>

<li><a href="#Complicated_Cookie_Reading">Complicated Cookie Reading</a></li>

<li><a href="#Reading_and_Writing_Multiple_Cookies">Reading and Writing Multiple Cookies</a></li>

<li><a href="#More_About_Cookies_2">More About Cookies</a></li>

<li><a href="#Cookie_Path_and_Domain">Cookie Path and Domain</a></li>



<li><a href="#Lesson_2_Review">Lesson 2 Review</a></li>

</ol>

</td></tr></tbody></table>



<a name="Fancy_String_Handling"></a><h4> <span class="mw-headline">Fancy String Handling</span></h4>

<p>Why do you have to learn about fancy string handling before getting into the joyous world of cookies? Well, it turns out that cookies are strings. To store visitor information, you have to first build a special cookie string. And then to read the information when the visitor returns, you have to decode the cookie string. To create and interpret these strings, you have to know your way around JavaScript&#8217;s string library.

</p><p>You should be pretty familiar with strings, since we&#8217;ve been working with them all along, but for a refresher, take a look at <a href="/2010/02/JavaScript_Tutorial_-_Lesson_2" title="Tutorial:JavaScript Tutorial - Lesson 2">Part I, Day 2</a> to see how to make an ordinary string bold:

</p>

<pre class="brush: js"> var normal_monkey = "I am a monkey!&lt;br&gt;";

 document.writeln("Normal monkey " + normal_monkey);

 var bold_monkey = normal_monkey.bold();

 document.writeln("Bold monkey " + bold_monkey);



</pre>

<p>The statement:

</p>

<pre class="brush: js"> var bold_monkey = normal_monkey.bold();

</pre>

<p>Is the same as the statement:

</p>

<pre class="brush: js"> var bold_monkey = "&lt;b&gt;" + normal_monkey + "&lt;/b&gt;";

</pre>

<p>The first version just looks neater. One of the many methods of the string object is <code>bold</code>, and it&#8217;s sort of silly. Less silly are the methods <code>indexOf, charAt, substring,</code> and <code>split</code>, which actually get inside strings and see what they&#8217;re made of. Let&#8217;s look at <code>indexOf</code> first.



</p>

<a name="indexOf"></a><h3> <span class="mw-headline">indexOf</span></h3>

<p>The <code>indexOf</code> finds the location of a set of characters inside a string and tells you where the substring starts. If the string doesn&#8217;t contain the substring, <code>indexOf</code> returns &#8220;-1.&#8221; Here are some examples:

</p>

<dl><dt> <code>var the_word = "monkey";</code>

</dt><dd>Let&#8217;s start with the word &#8220;monkey.&#8221;

</dd><dt> <code>var location_of_m = the_word.indexOf("m");</code>



</dt><dd>The <code>location_of_m</code> will be &#8220;0,&#8221; because that&#8217;s the starting position of a string.

</dd><dt> <code>var location_of_o = the_word.indexOf("o");</code>

</dt><dd>The <code>location_of_o</code> will be &#8220;1.&#8221;

</dd><dt> <code>var location_of_key = the_word.indexOf("key");</code>

</dt><dd><code>location_of_key</code> is &#8220;3&#8243; because the substring &#8220;key&#8221; starts with &#8220;k,&#8221; which is position three in the word &#8220;monkey.&#8221;



</dd><dt> <code>var location_of_y = the_word.indexOf("y");</code>

</dt><dd>The <code>location_of_y</code> is &#8220;5.&#8221;

</dd><dt> <code>var cheeky = the_word.indexOf("q");</code>

</dt><dd>The <code>cheeky</code> is &#8220;-1&#8243; because there&#8217;s no letter &#8220;q&#8221; in the word &#8220;monkey.&#8221;

</dd></dl>

<p>A more realistic use of <code>indexOf</code> is:



</p>

<pre class="brush: js"> var the_email = prompt("What's your email address?", "");

 var the_at_is_at = the_email.indexOf("@");

 if (the_at_is_at == -1)

 {

 	alert("You loser, email addresses must

 	have @ signs in them.");

 }

</pre>

<p>This little scrap of code asks users for their email address, and then checks to see if it&#8217;s a valid address. If the address doesn&#8217;t contain an @ sign, it can&#8217;t be valid. Enter <code>indexOf</code>, which checks for &#8220;@&#8221; in the string.

</p>

<a name="charAt"></a><h3> <span class="mw-headline">charAt</span></h3>

<p>The <code>charAt</code> finds out what letter is at a certain position inside a string. Here it is in action:

</p>

<pre class="brush: js"> var the_word = "monkey";

 var the_first_letter = the_word.charAt(0);

 var the_second_letter = the_word.charAt(1);

 var the_last_letter = the_word.charAt(the_word.length-1);



</pre>

<p>After this, <code>the_first_letter</code> is &#8220;m,&#8221; <code>the_second_letter</code> is &#8220;o,&#8221; and <code>the_last_letter</code> is &#8220;y.&#8221; Note that you can find out how many letters are in a word using the length property of the string. In this case, <code>the_word</code> is &#8220;monkey,&#8221; so <code>the_word.length</code> is &#8220;6.&#8221; Don&#8217;t forget that the first character of a string is at position &#8220;0&#8243; (as in <code>charAt(0)</code>), so the last letter will be in position <code>length-1</code>, which is why the last line features <code>the_word.length-1</code>.



</p><p>Before going over <code>substring</code> and <code>split</code>, let&#8217;s do an exercise with <code>charAt</code> and <code>indexOf</code>.

</p>

<a name="String_Exercise_1"></a><h3> <span class="mw-headline">String Exercise 1</span></h3>

<p>Your task is to write a script that will determine whether the last letter of a word is a vowel or a consonant. You can do it in a clever way, using both <code>indexOf</code> and <code>charAt</code>. Of course you <i>could</i> do it in a much less clever way without <code>indexOf</code>, but remember:the clever monkey gets the golden banana.



</p><p>Here&#8217;s an example of <a href="http://www.wired.com/wired/webmonkey/stuff/advanced_js_tutorial_files/vowel_checker.html" class="external text" title="http://www.wired.com/wired/webmonkey/stuff/advanced_js_tutorial_files/vowel_checker.html" rel="nofollow">it working</a>. When you&#8217;ve finished the exercise, or nearly died trying, learn how it&#8217;s done or double-check your work against <a href="http://www.wired.com/wired/webmonkey/stuff/advanced_js_tutorial_files/string_solution.html" class="external text" title="http://www.wired.com/wired/webmonkey/stuff/advanced_js_tutorial_files/string_solution.html" rel="nofollow">my solution</a>. Or, if you&#8217;re so pleased with your solution that you don&#8217;t want to sully your mind with mine, feel free to carry on with the string-a-thon.

</p>

<a name="Substring"></a><h4> <span class="mw-headline">Substring</span></h4>

<p>The <code>substring</code> is just like <code>charAt</code> except it can grab entire substrings from a word, not just letters. Here&#8217;s the format:

</p>



<pre class="brush: js"> var the_substring = the_string.substring(from, to);

</pre>

<p>&#8220;From&#8221; refers to the position of the first character of the substring, and &#8220;to&#8221; is, strangely enough, one greater than the last position of the substring. Using this weird method to mark the beginning and end of the substring makes it so that &#8220;to&#8221; minus &#8220;from&#8221; gives you the length of the substring:

</p>

<pre class="brush: js"> var the_string = "monkey";

 var clergy = the_string.substring(0,4);

 var tool = the_string.substring(3,6);

</pre>

<p>After this batch of code runs, &#8220;clergy&#8221; will equal &#8220;monk&#8221;; &#8220;tool&#8221; will equal &#8220;key.&#8221;

</p><p>The <code>substring</code> is often used with <code>indexOf</code> to break apart strings. For example, you could pull out the domain name of a given URL:

</p>



<pre class="brush: js"> var the_url = prompt("What's the URL?","");

 var lead_slashes = the_url.indexOf("//");

 var domain_start = lead_slashes + 2;

 var without_resource = the_url.substring(domain_start, the_url.length);

 var next_slash = without_resource.indexOf("/");

 var domain = without_resource.substring(0, next_slash);

</pre>

<p>Which means if you enter &#8220;<a href="http://www.webmonkey.com/javascript/index.html" class="external free" title="http://www.webmonkey.com/javascript/index.html" rel="nofollow">http://www.webmonkey.com/javascript/index.html</a>,&#8221; the domain will equal &#8220;www.webmonkey.com.&#8221; Try the <a href="http://www.wired.com/wired/webmonkey/stuff/advanced_js_tutorial_files/domain_grabber.html" class="external text" title="http://www.wired.com/wired/webmonkey/stuff/advanced_js_tutorial_files/domain_grabber.html" rel="nofollow">domain grabber</a> to see it work. If this code seems like kind of a drag to you, don&#8217;t worry. After I break it down line by line, I&#8217;ll show you how to make things much simpler using the <code>split</code> method. First, however, the analysis.

</p><p>The basic tactic we&#8217;re using here is to isolate everything between the first double slash and the next slash. Here&#8217;s how we do it:

</p>

<dl><dt> <code>var the_url = prompt("What's the URL?","");</code>



</dt><dd>This just asks the user for a URL. Let&#8217;s say they enter &#8220;<a href="http://www.webmonkey.com/javascript/index.html" class="external free" title="http://www.webmonkey.com/javascript/index.html" rel="nofollow">http://www.webmonkey.com/javascript/index.html</a>.&#8221;

</dd><dt> <code>var lead_slashes = the_url.indexOf("//");</code>

</dt><dd>This locates the first two slashes. In the case of our example URL, <code>lead_slashes</code> equals &#8220;5&#8243; because the two slashes start at position five. What&#8217;s that? You wonder, &#8220;if the string is a URL, it <i>always</i> starts with <code>http://</code>, so why don&#8217;t we just assume, oh so cleverly, that the two slashes start at position five instead of messing around with <code>indexOf</code>?&#8221; The thing is, you never know <i>what</i> people will do at the prompt. They might enter &#8220;the URL I want is <a href="http://www.blah.com/" class="external free" title="http://www.blah.com/" rel="nofollow">http://www.blah.com/</a>.&#8221; Or they might accidentally put a space before the URL. Or maybe they enter a URL that&#8217;s on a secure server, making it something like &#8220;<a href="https://www.whatever.com/" class="external free" title="https://www.whatever.com/" rel="nofollow">https://www.whatever.com/</a>.&#8221;One of the hardest things about programming is anticipating all possible cases and then coming up with a way to handle them. Ask people to drop information into an open text field, and you never quite know what you&#8217;ll get. So we can&#8217;t just assume that the two slashes are at positions five and six. Instead, we need to use the <code>indexOf</code> method to determine exactly where the two slashes start.



</dd><dt> <code>var domain_start = lead_slashes + 2;</code>

</dt><dd>This calculates the location of the first letter of the domain. Because there are two slashes, the first letter of the domain will be two positions over from the slashes.

</dd><dt> <code>var without_resource = the_url.substring(domain_start, the_string.length);</code>

</dt><dd>This grabs everything from the beginning of the domain name (which we determined in the previous line of code) and the end of the string. So, using the current example, <code>without_resource</code> is &#8220;www.webmonkey.com/javascript/index.html.&#8221;

</dd><dt> <code>var next_slash = without_resource.indexOf("/");</code>

</dt><dd>This figures out the position of the next slash in the string. Everything between the beginning of the string and this slash is domain name. In this case, the next slash is in position seventeen.

</dd><dt> <code>var domain = without_resource.substring(0, next_slash);</code>



</dt><dd>This final step grabs everything from the beginning of the string to the position of the next slash. In the current case, that makes domain equal to &#8220;www.webmonkey.com.&#8221;

</dd></dl>

<p>And there you have it. Yes, it&#8217;s a pain. If it makes you feel any better, string handling is a pain in almost all languages. JavaScript 1.2, which was introduced with Netscape 4.0, takes some strides toward making string handling easier. But it&#8217;s still a pain.

</p><p>The whole process can be handled quite a bit more easily with the <code>split</code> method.

</p>

<a name="The_Split_Method"></a><h4> <span class="mw-headline">The Split Method</span></h4>

<p>When you have a list of things separated by a delimiter, you generally use <code>split</code>. Say you have a list of names separated by commas &#8211; <code>split</code> takes that list and puts each of the names into an array. For example:



</p>

<pre class="brush: js"> var my_friends = "trixie,moxie,sven,guido,hermes";

 var friend_array = my_friends.split(",");

 for (var loop=0; loop &lt; friend_array.length; loop++)

 {

     document.writeln(friend_array[loop] + " is my friend.&lt;br&gt;");

 }

</pre>

<p>This breaks the string <code>my_friends</code> into an array of five elements. (Happily, JavaScript creates the array for you automatically, so you don&#8217;t have to use <code>new Array()</code> to create it yourself).

</p><p>After breaking the string into an array, we loop through it, writing out each friend&#8217;s name. If arrays or loops are unfamiliar to you, check out <a href="/2010/02/JavaScript_Tutorial_-_Lesson_4" title="Tutorial:JavaScript Tutorial - Lesson 4">Part I, Day 4</a> for an explanation.



</p><p>We can use <code>split</code> to make the earlier domain grabber easier to code:

</p>

<pre class="brush: js"> var the_url = prompt("What's the URL?","");

 var first_split = the_url.split("//");

 var without_resource = first_split[1];

 var second_split = without_resource.split("/");

 var domain = second_split[0];

</pre>

<p>This is much more attractive, and easier to understand, right? Here&#8217;s the breakdown:

</p>

<dl><dt> <code>var the_url = prompt("What's the URL?","");</code>

</dt><dd>As before, this requests a URL (let&#8217;s go with &#8220;<a href="http://www.webmonkey.com/javascript/index.html" class="external free" title="http://www.webmonkey.com/javascript/index.html" rel="nofollow">http://www.webmonkey.com/javascript/index.html</a>&#8221; again).

</dd><dt> <code>var first_split = the_url.split("//");</code>



</dt><dd>This splits the string into two pieces:<code>first_split[0]</code> is &#8220;http:&#8221; and <code>first_split[1]</code> is &#8220;www.webmonkey.com/javascript/index.html.&#8221;

</dd><dt> <code>var without_resource = first_split[1];</code>

</dt><dd>This just grabs the second element in the array, so now <code>without_resource</code> is &#8220;www.webmonkey.com/javascript/index.html.&#8221;

</dd><dt> <code>var second_split = without_resource.split("/");</code>



</dt><dd>This breaks <code>without_resource</code> into three pieces:<code>www.webmonkey.com</code>, <code>javascript</code>, and <code>index.html</code>. See how useful <code>split</code> is?

</dd><dt> <code>var domain = second_split[0];</code>

</dt><dd>Now all we have to do is grab the first element of the <code>second_split</code> array. And voila! We&#8217;re done.



</dd></dl>

<p>That might seem to be a lot of work at first, but you&#8217;ll get used to it pretty fast. I personally love <code>split</code> &#8211; it&#8217;s a special coding treat.

</p><p>Now that you&#8217;ve learned all the fancy string handling routines for cookies, take a breather &#8211; you&#8217;ve just digested quite a mouthful of information. Go for a little stroll. Have a snack. OK? Then it&#8217;s time to learn one last thing before sallying forth into cookie country:associative arrays.

</p>

<a name="Associative_Arrays"></a><h4> <span class="mw-headline">Associative Arrays</span></h4>

<p>If you&#8217;ve done any JavaScript programming, you&#8217;re probably familiar with arrays, which let you store lists of items and also give you access to the images, forms, and form elements of your HTML pages. In <a href="/2010/02/JavaScript_Tutorial_-_Lesson_4" title="Tutorial:JavaScript Tutorial - Lesson 4">Part I, Day 4</a>, I showed you how to create and manipulate arrays that are indexed by number. For example:

</p>

<pre class="brush: js"> var an_array = new Array("hickory","dickory");

 var element_one = an_array[0];

 var element_two = an_array[1];

 an_array[2] = "doc";

</pre>



<p>This creates a new array and initializes it with two strings. The first element of the array is accessed using its index number, &#8220;0.&#8221; The second element, element 1 of the array, is accessible with <code>an_array[1]</code>. You can add to an array by assigning something to a specific index of the array:in the example above, I made the third element of the array equal to &#8220;doc.&#8221; Now the array contains &#8220;hickory, dickory, doc.&#8221;

</p><p>Associative arrays are just like the array above, except rather than using numbers to index elements in the array, you use words.

</p>

<pre class="brush: js"> var phone_book = new Array();

 phone_book["sleepy"] = "(203) 555-1234";

 phone_book["happy"] = "(203) 555-2345";

</pre>

<p>This creates sort of a phone book. Access the phone number for &#8220;happy&#8221; by writing:

</p>

<pre class="brush: js"> var happy_number = phone_book["happy"];

</pre>

<p>Try out the working phone book example on the next page to see how an associative array might work (and get a major refresher on the use of JavaScript with forms at the same time).

</p>

<a name="Example_of_an_Associative_Array"></a><h4> <span class="mw-headline">Example of an Associative Array</span></h4>



<p><a href="http://www.wired.com/wired/webmonkey/stuff/advanced_js_tutorial_files/associative_array.html" class="external text" title="http://www.wired.com/wired/webmonkey/stuff/advanced_js_tutorial_files/associative_array.html" rel="nofollow">Click here</a>.

</p><p>This example is a bit involved, so let&#8217;s go through it slowly. First let&#8217;s look at the phone book itself. The phone book, which is defined in the header ( <code>phone_book</code>) and has seven entries, looks like this:

</p>

<pre class="brush: js"> var phone_book = new Array();

 phone_book["happy"] = "(203) 555-1234";

 phone_book["sleepy"] = "(203) 555-2345";

 phone_book["sneezy"] = "(203) 555-4321";

 phone_book["sleazy"] = "(203) 555-3245";

 phone_book["sneery"] = "(203) 555-3213";

 phone_book["bleary"] = "(203) 555-2365";

 phone_book["tweaked"] = "(203) 555-1664";

</pre>

<p>The key to each entry is the name of the dwarf, and the value of each entry is that dwarfs&#8217;s phone number. When we want to get a phone number for our favorite dwarf, say &#8220;Sneezy,&#8221; we write this:

</p>

<pre class="brush: js"> var the_number = phone_book["sneezy"];

</pre>

<p>Now let&#8217;s look at the form:

</p>

<pre class="brush: js"> &lt;form name="the_form"&gt;



 &lt;b&gt;Name:&lt;/b&gt;

 &lt;select onChange =

 "displayNumber(phone_book,this.options[selectedIndex].value);"&gt;

 &lt;option value="happy"&gt;Happy

 &lt;option value="sleepy"&gt;Sleepy

 &lt;option value="sneezy"&gt;Sneezy

 &lt;option value="sleazy"&gt;Sleazy

 &lt;option value="sneary"&gt;Sneery

 &lt;option value="bleary"&gt;Bleary

 &lt;option value="tweaked"&gt;Tweaked

 &lt;/select&gt;



 &lt;p&gt;

 &lt;b&gt;Number&lt;/b&gt;

 &lt;input type="text" name="number_box" value=""&gt;

 &lt;/form&gt;

</pre>

<p>Note that the form and the elements inside the form have names. This allows us to read and write to the form elements. Also, take a look at the <code>onChange</code> handler in the select tag. This says that when the <code>select</code> is changed, it calls the function <code>displayNumber</code>, which is defined up in the header. If I use the pulldown to select &#8220;sneezy,&#8221; the expression <code>this.options[selectedIndex].value</code> returns &#8220;sneezy.&#8221; If you need a refresher on this kind of form madness, check out <a href="/2010/02/JavaScript_Tutorial_-_Lesson_5" title="Tutorial:JavaScript Tutorial - Lesson 5">Part I, Day 5</a>. Once we&#8217;ve figured out what the user has selected, we jump to the <code>displayNumber</code> function, which looks like this:



</p>

<pre class="brush: js"> function displayNumber(phone_book, entry)

 {

     var the_number = phone_book[entry];

     window.document.the_form.number_box.value = the_number;

 }

</pre>

<p>It takes two parameters &#8211; a phone book and a name &#8211; to make this function work. The first line of the function,

</p>

<pre class="brush: js"> var the_number = phone_book[entry];

</pre>

<p>looks the name up in the phone book, and the next line,

</p>

<pre class="brush: js"> window.document.the_form.number_box.value = the_number;

</pre>

<p>puts that number into the form element called <code>number_box</code>.



</p><p>And there you have it. As you can see, associative arrays are a good way to link one string to another. They&#8217;re useful for linking names to phone numbers, to passwords, to birthdays, and all kinds of things. A few lessons from now, I&#8217;ll introduce another useful trick you can do with associative arrays, so don&#8217;t cast them into the facts-best-forgotten pit quite yet.

</p><p>And now, if you&#8217;re ready for it, let&#8217;s sink our teeth into cookies!

</p>

<a name="Cookie_Introduction"></a><h4> <span class="mw-headline">Cookie Introduction</span></h4>

<p>Now that you&#8217;ve mastered advanced string handling and associative arrays, it&#8217;s time to open up the cookie jar. As I mentioned earlier, cookies are little bits of information that you can leave on a user&#8217;s hard drive, where they stay even after the user leaves your site or turns off the computer, which is extremely useful when you want to remember information about repeat visitors.

</p><p>Let&#8217;s look at a basic example of a working cookie. In this example, we set a cookie on one page and then read it from another page. As you play around with the example, try to think about how you would do this without cookies. Here&#8217;s the very basic example of <a href="http://www.wired.com/wired/webmonkey/stuff/advanced_js_tutorial_files/cookie_example.html" class="external text" title="http://www.wired.com/wired/webmonkey/stuff/advanced_js_tutorial_files/cookie_example.html" rel="nofollow">a working cookie</a>.

</p><p>Had your fill of cookie dough tasting? Let&#8217;s move on to the next step of the recipe.

</p>

<a name="More_About_Cookies"></a><h4> <span class="mw-headline">More About Cookies</span></h4>

<p>Because cookies involve writing to, and reading from, users&#8217; hard drives, security issues arise that the people who wrote Netscape, MSIE, and the other cookie-friendly browsers had to confront. The most important limitations for this tutorial are:

</p>



<ol><li> Not everyone has a cookie-friendly browser (but most do).

</li><li> Not everyone who has a cookie-friendly browser will accept your cookies (but most will).

</li><li> Each domain is allotted only 20 cookies, so use them sparingly.

</li><li> Cookies must be no larger than 4 KB. That&#8217;s just over 4,000 characters, which is plenty.

</li></ol>

<p>With those limitations in mind, let&#8217;s learn about setting cookies.

</p>

<a name="Setting_Cookies"></a><h3> <span class="mw-headline">Setting Cookies</span></h3>

<p>Setting a basic cookie is very easy. All you have to do is create a string in the form of <code>cookie_name=value</code> and then set the <code>document.cookie</code> property to that. The only trick:cookie values must never have spaces, commas, or semicolons. Happily, you don&#8217;t really have to worry about this because a pair of functions will code and decode your properties:they are <code>escape()</code> and <code>unescape()</code>.



</p><p>Our simple example, which stored your name as a cookie, looks like this:

</p>

<pre class="brush: js">function setCookie()

{

    var the_name = prompt("What's your name?","");



    var the_cookie = "wm_javascript=" + escape("username:" + the_name);



    document.cookie = the_cookie;



    alert("Thanks, now go to the next page.");



}

</pre>

<p>The middle two lines of this function are the critical ones:

</p>

<dl><dt> <code>var the_cookie = "wm_javascript=" + escape("username:" + the_name);</code>

</dt><dd>If I entered &#8220;dave thau&#8221; at the prompt, this line would create a string that looks like <code>wm_javascript=username%3Adave%20thau</code>. This means that I&#8217;m going to save a cookie named <code>wm_javascript</code> to the hard drive. That cookie is going to have the value <code>username%3Adave%20thau</code> &#8211; the escape() function replaced the colon after username with <code>%3A</code> and the space between &#8220;dave&#8221; and &#8220;thau&#8221; with a <code>%20</code>.When we read the cookie, we&#8217;re going to look for the cookie named <code>wm_javascript</code>, then grab the <code>username%3Adave%20thau</code>, unescape() it, which changes the <code>%3A</code> back to a colon and the <code>%20</code> back into a space, and then chop off the <code>username:</code>.



</dd><dt> <code>document.cookie = the_cookie;</code>

</dt><dd>And this sets the cookie. Easy, huh?

</dd></dl>

<p>Now let&#8217;s learn how to read cookies.

</p>

<a name="Reading_Cookies"></a><h4> <span class="mw-headline">Reading Cookies</span></h4>

<p>Once you save a cookie to someone&#8217;s hard disk, it&#8217;s easy to read. Here&#8217;s the code that reads the example cookie:

</p>

<pre class="brush: js">function readCookie()

{

    var the_cookie = document.cookie;

    var the_cookie = unescape(the_cookie);

    var broken_cookie = the_cookie.split(":");

    var the_name = broken_cookie[1];

    alert("Your name is:" + the_name);

}

</pre>

<p>The first line is the important one. Whenever your browser opens a Web page, it calls in whatever cookies it can, then loads them into the <code>document.cookie</code> property.



</p><p>The tricky part about reading cookies is getting the information you want out of them. Remember, the cookie we set looks like this:<code>wm_javascript=username%3Adave%20thau</code>. Everything after the first line of the function is devoted to pulling the username out of the cookie. Here&#8217;s a breakdown of that process:

</p>

<dl><dt> <code>var the_cookie = unescape(the_cookie);</code>

</dt><dd>Undo the stuff that the escape() function created. In this case, unescape() swaps the <code>%3A</code> with a colon, and the <code>%20</code> with a space.

</dd><dt> <code>var broken_cookie = the_cookie.split(":");</code>



</dt><dd>Split the cookie into two parts at the colon.

</dd><dt> <code>var the_name = broken_cookie[1];</code>

</dt><dd>Grab the part after the colon, which is dave thau.

</dd><dt> <code>alert("Your name is:" + the_name);</code>

</dt><dd>Yee-haw!

</dd></dl>

<p>This example used a cookie that only stored one bit of information:the username. As I said before, cookies can store up to 4 KB, which leaves plenty of room for quite a bit more information.

</p>

<a name="Complicated_Cookie_Reading"></a><h3> <span class="mw-headline">Complicated Cookie Reading </span></h3>

<p>If you want your cookie to contain more than just one piece of information, you can make the value of the cookie as long as you want (up to the 4000 character limit). Say you&#8217;re looking to store a person&#8217;s name, age, and phone number. You do something like this:

</p>



<pre class="brush: js">var the_cookie = "username:thau/age:older than the hills/phone:411";

document.cookie="my_happy_cookie=" + escape(the_cookie);

</pre>

<p>I use a slash to separate property names and a colon to distinguish the property name from the property value. The slash and colon are arbitrary choices &#8211; they could be anything, like say, this:

</p>

<pre class="brush: js">var the_cookie = "username=thau&amp;age=older than the hills&amp;phone=411";

document.cookie="my_happy_cookie=" + escape(the_cookie);

</pre>

<p><br />

The delimiters you choose are up to you. Just remember what you used so you can decode the cookie later.

</p><p><br />

As with our simple example, the easy part is setting the cookie. Things get a little sticky, however, when it comes to pulling the information out of the cookie when you need it. I suggest using associative arrays to store all the information. For example, let&#8217;s say you saved this to someone&#8217;s hard drive:

</p>

<pre class="brush: js">my_happy_cookie=username:thau/age:older than the hills/phone:411

</pre>

<p>You could put the information into a handy associative array like this:

</p>



<pre class="brush: js">function readTheCookie(the_info)

{

// load the cookie into a variable and unescape it



var the_cookie = document.cookie;

var the_cookie = unescape(the_cookie);



// separate the values from the cookie name



var broken_cookie = the_cookie.split("=");

var the_values = broken_cookie[1];



// break each name:value pair into an array



var separated_values = the_values.split("/");



// loop through the list of name:values and load

// up the associate array



var property_value = "";



for (var loop = 0; loop &lt; separated_values.length; loop++)



{

property_value = separated_values[loop];

var broken_info = property_value.split(":");

var the_property = broken_info[0];

var the_value = broken_info[1];

the_info[the_property] = the_value;

}



}

</pre>

<p>If you had this function in your JavaScript, you could call it like this:

</p>

<pre class="brush: js">var cookie_information = new Array();

readTheCookie(cookie_information);

</pre>

<p>And then you&#8217;d have <code>cookie_information["username"], cookie_information["age"],</code> and <code>cookie_information["phone"]</code> set correctly.

</p><p><br />

This may look a little funky, but actually it&#8217;s not that hard. Here&#8217;s a step-by-step analysis of what&#8217;s going on:



</p><p><br />

</p>

<dl><dt> <code>var the_cookie = document.cookie;</code>

</dt></dl>

<dl><dd>This is the easy part. It puts the cookie into a variable.

</dd></dl>

<dl><dt> <code>var the_cookie = unescape(the_cookie);</code>

</dt></dl>

<dl><dd>Undo the work of escape().

</dd></dl>

<dl><dt> <code>var broken_cookie = the_cookie.split("=");<br /> var the_values = broken_cookie[1];</code>



</dt></dl>

<dl><dd>These lines make <code>the_values</code> equal to <code>username:thau/age:older than the hills/phone:411</code>.

</dd></dl>

<dl><dt> <code>var separated_values = the_values.split("/");</code>

</dt></dl>

<dl><dd>This makes an array called <code>separated_values</code> that contains three elements:<code>separated_values[0] = "username:thau"<br /> separated_values[1] = "age:older than the hills"<br /> separated_values[2] = "phone:411"<br /></code>



</dd></dl>

<dl><dt> <code>for (loop = 0; loop &lt; separated_values.length; loop++) </code>

</dt></dl>

<dl><dd>This loops through the three elements of <code>separated_values</code>.

</dd></dl>

<dl><dt> <code>property_value = separated_values[loop];</code>

</dt></dl>

<dl><dd>This grabs the current <code>name:value pair</code>, the first one being <code>username:thau</code>.



</dd></dl>

<dl><dt> <code>var broken_info = property_value.split(":");</code>

</dt></dl>

<dl><dd>This breaks the pair into two elements into an array called <code>broken_info</code> where <code>broken_info[0] = "username"<br /> broken_info[1] = "thau"<br /></code>

</dd></dl>

<dl><dt> <code>var the_property = broken_info[0];</code>



</dt></dl>

<dl><dd>The first time through the loop, <code>the_property</code> will be &#8220;username&#8221;

</dd></dl>

<dl><dt> <code>var the_value = broken_info[1];</code>

</dt></dl>

<dl><dd><code>the_value</code> will be &#8220;thau.&#8221;

</dd></dl>

<dl><dt> <code>the_info[the_property] = the_value;</code>



</dt></dl>

<dl><dd>Here&#8217;s where associative arrays come in handy. This makes <code>the_info["username"] = "thau"</code>. So now, when you want the username from the cookie, you can just say something like <code>var the_name = the_info["username"];</code>.

</dd></dl>

<dl><dt> And so on

</dt></dl>

<dl><dd>Each time through the loop, a new element gets added to <code>the_info</code>. At the end of the loop is <code>the_info["username"] = "thau", the_info["age"] = "old as the hills"</code> and <code>the_info["phone"] = 411</code>.



</dd></dl>

<p>It <i>is</i> a bit cumbersome, but it&#8217;s the way I prefer to get large quantities of information in and out of cookies. There are lots of ways to do it, and if you find another way that you like, all the power to you.

</p><p>Okay, the last thing you need to know is what to do when you&#8217;re dishing out multiple cookies.

</p><p><br />

</p>

<a name="Reading_and_Writing_Multiple_Cookies"></a><h3> <span class="mw-headline">Reading and Writing Multiple Cookies </span></h3>

<p>On the last page, we learned how to cram lots of information into one cookie. Another way to do this is with multiple cookies.

</p><p>Saving multiple cookies is very straightforward. We&#8217;ve learned that every cookie has a name. In the last example, we named the cookie <code>my_happy_cookie</code>, and did something like this:

</p>

<pre class="brush: js">var the_cookie = "my_happy_cookie=happiness_and_joy";

document.cookie = the_cookie;



</pre>

<p>To save multiple cookies, just give each cookie a different name. If you&#8217;re adding a new cookie, setting <code>document.cookie</code> doesn&#8217;t delete cookies that are already there. So if we do this:

</p>

<pre class="brush: js">var the_cookie = "my_happy_cookie=happiness_and_joy";

document.cookie = the_cookie;

var another_cookie= "my_other_cookie=more_joy_more_happiness";

document.cookie = another_cookie;

</pre>

<p>You&#8217;ll now have access to <i>both</i> cookies. It&#8217;s sort of weird, so make sure you understand what&#8217;s going on.

</p><p>Let&#8217;s assume you executed the last block of code and you want to access <code>my_happy_cookie</code>. If you look at <code>document.cookie</code>, you&#8217;ll see this:



</p>

<pre class="brush: js">my_happy_cookie=happiness_and_joy;

my_other_cookie=more_joy_more_happiness;

</pre>

<p>If you don&#8217;t believe me, just <a href="http://www.wired.com/wired/webmonkey/stuff/advanced_js_tutorial_files/multiple_cookies.html" class="external text" title="http://www.wired.com/wired/webmonkey/stuff/advanced_js_tutorial_files/multiple_cookies.html" rel="nofollow">look at your cookie</a>.

</p><p>This is very nice, but it makes reading a specific cookie a bit more difficult. Here&#8217;s some (slightly simplified) code that allows you to isolate a specific cookie:

</p>

<pre class="brush: js">function WM_readCookie(name) {

if (document.cookie == '') {



// there's no cookie, so go no further



return false;

} else {



// there is a cookie



var firstChar, lastChar;

var theBigCookie = document.cookie;

firstChar = theBigCookie.indexOf(name);



// find the start of 'name'



if(firstChar&nbsp;!= -1) {



// if you found the cookie



firstChar += name.length + 1;



// skip 'name' and '='



lastChar = theBigCookie.indexOf(';', firstChar);



// Find the end of the value string (i.e. the next ';').



if(lastChar == -1) lastChar = theBigCookie.length;



return unescape(theBigCookie.substring(firstChar, lastChar));



} else {



// If there was no cookie of that name, return false.



return false;

}



}



}



// WM_readCookie

</pre>

<p>Since this is very well commented, I&#8217;ll just let you take a look at it and figure out what&#8217;s happening on your own (c&#8217;mon, you know everything you need to know to make sense of this).

</p><p>Once you&#8217;ve parsed that information, let&#8217;s leave our &#8220;setting and reading basic cookies&#8221; discussion and look at some of the cooler things you can do with cookies.

</p>

<a name="More_About_Cookies_2"></a><h3> <span class="mw-headline">More About Cookies</span></h3>



<p>So far, you&#8217;ve learned how to set and read a basic cookie. Unfortunately, your basic cookie will get deleted automatically when a user quits out of the browser. Sometimes this is for the best. Since each domain, such as webmonkey.com, is allowed only 20 cookies on any user&#8217;s machine, you don&#8217;t want to waste space with cookies that aren&#8217;t saved between browser sessions.

</p><p>However, if you do want to save cookies on users&#8217; hard drives, you have to set an expiration date, which has to be in a special format called GMT. For example:

</p>

<pre class="brush: js">Mon, 27-Apr-1998 00:00:00 GMT

</pre>

<p>(This is the date on which Koko the gorilla had her AOL chat session.)

</p><p>Getting the GMT right can be sort of a pain, especially when it comes to figuring out the day of the date. Is it a Monday? A Friday? To make things easier on you, JavaScript has a date method called <code>toGMTString</code>. Here&#8217;s an easy way to set an expiration date to some distant time in the future:

</p>

<pre class="brush: js">var the_date = new Date("December 31, 2023");

var the_cookie_date = the_date.toGMTString();

</pre>

<p>Once you establish an expiration date for your cookie, you have to add this information before you set the cookie. Therefore, your cookie should look like this:

</p>

<pre class="brush: js">cookie_name=blah_blah;expires=date

</pre>

<p>Basically, you&#8217;re just adding <code>expires=date</code> to the cookie string and separating the different cookie components with a semicolon.



</p><p>Here&#8217;s how to build a cookie that will last until the end of the Mayan calendar:

</p>

<pre class="brush: js">function setCookie()

{



// get the information



//



var the_name = prompt("What's your name?","");

var the_date = new Date("December 31, 2023");

var the_cookie_date = the_date.toGMTString();





// build and save the cookie



//



var the_cookie = "my_cookie=" + escape(the_name);

the_cookie = the_cookie + ";expires=" + the_cookie_date;

document.cookie = the_cookie;



}

</pre>

<p>At the end of all this, <code>the_cookie</code> will look something like this:

</p>

<pre class="brush: js">my_cookie=thau;expires=Fri, 31-Dec-2023 00:00:00 GMT

</pre>

<p>When this cookie is set, it will live on the user&#8217;s hard drive until the expiration date.

</p><p>The expiration date also allows you to delete cookies you don&#8217;t want users to have any more. If you set the expiration date of a cookie to a time that&#8217;s already passed, the cookie will be deleted from the cookie file.

</p><p>In addition to <code>name</code> and <code>expires</code>, there are two other important cookies components that you&#8217;ll need to know about: path and domain.



</p>

<a name="Cookie_Path_and_Domain"></a><h3> <span class="mw-headline">Cookie Path and Domain</span></h3>

<p>This is the last tricky cookies hurdle: By default, a cookie can be read only by HTML pages that sit on the same web server and in the same directory as the page that set the cookie.

</p><p>For example, if you have a JavaScript on &#8220;<a href="http://chimp.webmonkey.com/food/bananas/banana_puree.htm" class="external free" title="http://chimp.webmonkey.com/food/bananas/banana_puree.htm" rel="nofollow">http://chimp.webmonkey.com/food/bananas/banana_puree.htm</a>&#8221; that asks people for their names, you might want to access a given name on another one of your Web pages, such as the homepage (<a href="http://chimp.webmonkey.com/" class="external free" title="http://chimp.webmonkey.com/" rel="nofollow">http://chimp.webmonkey.com/</a>.) To allow this, you have to set the &#8220;path&#8221; of the cookie. The &#8220;path&#8221; sets the top level directory from which a cookie can be read. Set the path of a cookie to the top-level directory of your Web pages, and the cookie is readable by all your Web pages.

</p><p>Do this by adding <code>path=/;</code> to your cookie. If you just wanted the cookie readable solely in the &#8220;food&#8221; directory, you&#8217;d add <code>path=/food;</code> to your cookie.



</p><p>A second hitch is that some Web sites have lots of little domains. For example, Webmonkey might have pages at &#8220;chimp.webmonkey.com,&#8221; &#8220;gorilla.webmonkey.com,&#8221; and &#8220;ape.webmonkey.com.&#8221; By default, if a Web page on &#8220;chimp.webmonkey.com&#8221; sets a cookie, only pages on &#8220;chimp.webmonkey.com&#8221; can read it. If we wanted all the machines in the &#8220;webmonkey.com&#8221; domain to read the cookie, we&#8217;d have to add &#8220;domain=webmonkey.com&#8221; to the cookie. Don&#8217;t get clever though. Pages at &#8220;republicans.com&#8221; can&#8217;t set or read cookies from &#8220;democrats.com.&#8221;

</p><p>To put all the above together &#8211; set a cookie on the Web page &#8220;<a href="http://chimp.webmonkey.com/food/bananas/banana_puree.htm" class="external free" title="http://chimp.webmonkey.com/food/bananas/banana_puree.htm" rel="nofollow">http://chimp.webmonkey.com/food/bananas/banana_puree.htm</a>&#8221; that we want to be readable by all Webmonkey pages &#8211; we&#8217;d have to do this:

</p>

<pre class="brush: js">function setCookie()

{

var the_name = prompt("What's your name?","");

var the_cookie = "cookie_puss=" + escape(the_name) + ";"&nbsp;;

var the_cookie = the_cookie + "path=/;";

var the_cookie = the_cookie + "domain=webmonkey.com;";

document.cookie = the_cookie;

}

</pre>

<p>And so ends the cookies lesson. Let&#8217;s review what we&#8217;ve learned so far and then go onto a final exercise.

</p>

<a name="Lesson_2_Review"></a><h3> <span class="mw-headline">Lesson 2 Review</span></h3>

<p>Today was a big day, probably the biggest in this set of lessons. However, the things you learned today take you a significant step closer to the ability to create JavaScripts that are more than just cute. For example, today&#8217;s homework assignment is to add a &#8220;bookmarks&#8221; feature to your do-it-yourself Web browser.

</p><p>Here are the main topics we covered today:

</p>

<dl><dt> Advanced String Handling



</dt><dd>Including

<ul><li> <code>charAt</code> &#8211; getting a character at a certain position

</li><li> <code>indexOf</code> &#8211; getting the position of a character

</li><li> <code>substring</code> &#8211; getting a piece of a string

</li><li> <code>split</code> &#8211; splitting a string up into an array



</li></ul>

</dd></dl>

<dl><dt> Associative Arrays

</dt><dd>Another JavaScript datatype useful for storing things like phone books, password lists, birthdays, and cookie information

</dd><dt> Cookies

</dt><dd>How to set them, read them, and make them permanent

</dd></dl>

<p>Tomorrow we&#8217;ll cover:

</p>

<ul><li> Preloading images to speed up image swaps

</li><li> Creating your own objects and a do-it-yourself virtual pet

</li><li> Getting to hard-to-find objects



</li></ul>

<p><br />

Before closing the JavaScript book entirely for the day, you can hone your knowledge by trying this <a href="http://www.wired.com/wired/webmonkey/stuff/advanced_js_tutorial_files/AJST_homework2.html" class="external text" title="http://www.wired.com/wired/webmonkey/stuff/advanced_js_tutorial_files/AJST_homework2.html" rel="nofollow">homework assignment</a>.

</p><p>OK, ready? <a href="/2010/02/Advanced_JavaScript_Tutorial_-_Lesson_3" title="Tutorial:Advanced JavaScript Tutorial - Lesson 3">Next</a>!

</p><div id='linker_widget' class='contextly-widget'></div>]]></content:encoded>
            <wfw:commentRss>http://www.webmonkey.com/2010/02/advanced_javascript_tutorial_-_lesson_2/feed/</wfw:commentRss>
        <slash:comments>0</slash:comments>

        
    </item>
    </channel>
</rss>
