Click here to Skip to main content
Click here to Skip to main content

JavaScript Page Cookie (maintaining page state)

, 12 May 2008 CPOL
Rate this:
Please Sign up or sign in to vote.
Sometimes you need to redirect the user from the current page to accomplish a part of a task. Most people use pop-up windows to refrain from doing this, but sometimes you just can't do it any other way.

Disclaimer

The author does not accept responsibility for any effects, adverse or otherwise, that this code may have on you, your computer, your sanity, your dog, and anything else that you can think of. Use it at your own risk. (Deja Vu? I also love the Allegro disclaimer.)

Quick and dirty tour

So you don't like to read all articles you see on the web, or you don't have time for it? Then, just download the source files, and open the " pageCookieDemo.htm" file on your favorite browser.

Background

Although the inner works require you to be an advanced web developer to understand and improve it, you need only to have basic knowledge of HTML and JavaScript to use the tool.

Introduction

Sometimes you need to redirect the user from the current page to accomplish a part of a task. Most people use pop-up windows to refrain from doing this, but sometimes you just can't do it any other way. Anyway, keeping the page controls state between navigation is indeed a useful tool for your bat belt.

Keeping the state (and the user)

The tool is composed of two js files, one handles browser cookies and the other is a specialization for page state handling.

<html>
    <head>
        <title>Debug Demo</title>
        
        <script type="text/javascript" src="debuggingtools.js "></script>
        <script type="text/javascript" src="Cookie.js"></script>
        <script type="text/javascript" src=" PageCookie.js"></script>

...
    </head>

Please refer to JavaScript Debugging Tool article for information about it.

The Cookie

You may have seem dozen different cookie handling functions around. Despite the fact the object-oriented style coding, there ain't much news about how to handle a cookie. First, we create the cookie class that will handle all data.

var Cookie = function(name, value, path, expires, domain, secure)
{
    this.Name = name;
    this.Value = value;
    this.Path = path;
    this.Expires = expires;
    this.Domain = domain;
    this.Secure = secure;
}

Now we add some control with the JavaScript way to do static methods: prototype. Remember that no cookie can be larger than 4KB. Trying to save a cookie larger than that would generate an empty cookie on most browsers so, to avoid headaches, we will throw an exception when it occurs.

Cookie.prototype.MaxSize = 4000; //size in KB

Cookie.prototype.toString = function()
{
    return this.Value;
}

Cookie.prototype.Append = function(newValue)
{
     this.Value += newValue;
}

The toString() function may catch your attention here. It simply allows us to use the cookie object as it was a variable directly. For example, both methods bellow are equivalent:

    alert( myCookie.Value );
    alert( myCookie );

Since I don't want you to bother on how to extract the value of a cookie, the internal function $GetValue will do the job for you and save the value into the .Value property. The .Load(), .Save(), and .Delete() methods do exactly what their names suggests. Let's get to some code. The cookieDemo.htm page shows how you can create, save, load and delete cookies. Try those operations in the order:

  • LOAD: no cookie with that name should be present, the value will be null.
  • DELETE: no cookie to delete, but no error will occur.
  • SAVE: creating a cookie with "myValue" as a value for it.
  • LOAD: the cookie should be present and the value will be "myValue".
  • DELETE: cookie will be deleted.
  • LOAD: no cookie with that name should be present, the value will be null.
<button onclick="ShowMe('loadCookie');" ID="Button1">loadCookie</button> 
...
    function ShowMe(type)
    {
        try
        {                
            switch(type)
            {
                case "loadCookie":
                    alert( new Cookie("demo").Load() ); 
                    break;
                case "saveCookie":
                    new Cookie("demo", "myValue").Save();
                    alert("saved.");
                    break; 
                case "deleteCookie":
                    new Cookie("demo").Delete();
                    alert("deleted.");
                    break;
            }
        } 
        catch(ex)
        {
            debugHelper.Exception(ex.message, document.URL, 
                        document.lastModified, document.referrer);
        }
    }
...

The Page Cookie

Since there's a limit of 20 cookies per domain (URL), you can't save the state of each control in a separated cookie_name:cookie_value style. Using the page cookie is straightforward.

 
...
    function ShowMe(type)
    {
        try
        {                
            switch(type)
            {
                case "GetPageState":
                    var pc = new PageCookie( document.URL);
                    pc.GetPageState();
                    pc.Save();
                    alert("saved.");
                    break;
                case "RestorePageState": 
                    var pc = new PageCookie(document.URL);
                    pc.Load();
                    pc.RestorePageState();
                    alert("restored.");
                    break; 
                case "DeletePageState":
                    new PageCookie(document.URL).Delete();
                    alert("deleted.");
                    break;
                case "RefreshPage": 
                    window.location = window.location;
                    break;
            }
        }
        catch(ex)
        {
            debugHelper.Exception(ex.message, document.URL, 
                        document.lastModified , document.referrer);
        }
    }

All we do here is to specialize the Cookie class so it can read a page control values and save all in one cookie only. On the example above, we used document.URL as a cookie name, so each page will have its own cookie and you could safely copy & paste the code on other pages.

    var PageCookie = function(pageName)
    { 
        this.base = Cookie;
        this.base(pageName);
        
        this.PageName = pageName;
    }
    PageCookie.prototype = new Cookie();
    PageCookie.prototype.constructor = PageCookie;

Since this article is for beginners, I do not intend to explain the inner works of Cookie and PageCookie methods here. If you need more information, feel free to post a comment at the bottom of this page.

Persistence

A quick word about cookie persistence is recommended here. You may have noticed that, by default, the cookie is session based. This means that if you close the browser, the cookies will be lost. If you need to persist cookies for a period of time, you need to change the cookie property .Expires (in UTC time format). For example: myCookie.Expires = "Thu, 26 May 2006 12:17:25 UTC". On Google you can find numerous examples of cookie expiration.

Password and File fields (oh my)

"There's always a catch", said Constantine once. And it is true for cookie also. By security reasons, you cannot get a input type Password field value by JavaScript code. At last, not doing it the simple way, and it is really *not* recommended to store sensitive data on cookies. Another interesting field is the input type file, used to upload files to a server. This field value property is read-only, which means that no script can capture undesired files on your machine and upload it to even more undesired servers.

A word about cross-domain scripting

I think it is necessary to add some comments about some caveats when using cookies. By default, if you create a cookie on a page inside [www.asp.net/ajax] this cookie is invisible for other web locations like [www.asp.net]. You can work around this by setting the cookie property PATH to the root of your site. For instance, open the pageCookie.js file and edit the file like the code below:

var PageCookie = function(pageName)
{
    this.base = Cookie;
    this.base(pageName);

    this.Path = "/";
    //new line added to set cookie path

    this.PageName = pageName;
}

Also, all cookies have a Domain property. For security sake, no cookie from [www.domainA.com] can access cookies of [ www.domainB.com]. But this also means that cookies from [lib.library.com ] can't access cookies of [www.library.com], which may lead to sub-domain problems.
This last case can be solved setting the Domain property of the page cookies to [ library.com]. And don't think you can fool browsers by lying about your real domain name. They're a lot smart these days and won't let you use a domain you're not in.

...
    var pc = new PageCookie(document.URL);
    pc.Domain = "myDomain.com";   //use common domain for all cookies 
    pc.GetPageState();
    pc.Save();
...

Note that I did *not* change any of this behaviors on this article source-code. Those are the default actions of a browser and you should change them for your own specific needs when required.

Conclusion

And that's it for the JavaScript page cookie tool! I hope you find many uses for it.

References

Some great resources on the web:

History

  • 11-08-2006:
    • Original article.
  • 12-01-2006:
    • Came to my attention to add some words about cross-domain issues (path and domain properties). Thanks goes to James Mendham.
  • 05-11-2008:
    • Added support for select-multiple (list boxes). Thanks to Jonathan Romero's reminder.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Roberto Colnaghi
Software Developer
United States United States
I'm a passionate developer and videogame player.
Been in touch with Objective-C, Javascript, C#, C, Guild Wars 2, Tera and many more.
 
Javascript is one of my favorite languages.
Follow on   Twitter   Google+

Comments and Discussions

 
Generalusing script with javascript tree Pinmemberanand sueman4-Jan-11 1:15 
GeneralNice one! PinmemberSandeep Mewara24-Mar-10 6:31 
GeneralNice read... PinmemberRajesh Pillai9-Nov-06 8:38 
GeneralRe: Nice read... PinmemberRoberto 'Obi-Wan' Colnaghi Junior9-Nov-06 12:18 
GeneralRe: Nice read... PinmemberRajesh Pillai11-Nov-06 19:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.1411023.1 | Last Updated 12 May 2008
Article Copyright 2006 by Roberto Colnaghi
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid