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;
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 = "/";
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";
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:
- 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.