Take your cookies to the next level with Subcookies
Posted on 27 May 2007 (01:30 AM)
Cookies provide an easy way to save some user data. They can be a nice aid in usability, as they give you a way of remembering certain choices made by the user.
Browsers have placed some restrictions on the storage capacity of a cookie, though. They usually allow only 20 cookies to be stored per domain or server. To circumvent this problem, I'll explain a technique called "subcookies" to you and show you an easy Javascript way of accessing the so-called subcookies.
The article has been down for a day, unfortunately, due to a PHP error. I'm terribly sorry! The article is fixed now, do check it out :)Access to regular cookies
First, let's take a quick look at the cookiejar object. An object I've written to provide easy access to cookies. First of all; the functionality of the object is written by Peter-Paul Koch (http://www.quirksmode.org/js/cookies.HTML). All I did was wrap it all in one object and add automatic escaping of cookie data. Credit where credit's due, eh? :)
The cookiejar object has three methods:
bake: function(cookieName,cookieValue,days,path){fetch: function(cookieName){crumble: function(cookieName){- Download this code: /code/subcookies1.txt
The bake method creates a new cookie. Parameters are the name of the cookie, the value of the cookie, the days (as an integer) after which the cookie will expire and the path in which the cookie is accessible.
The fetch method is used to get the value of a given cookie. It takes one parameter; the name of the cookie. Lastly, the crumble method destroys a cookie, which name is given in the only parameter.
Example:
// set a cookie named 'admin' with a value of 'Harmen' to expire after 2 dayscookiejar.bake ('admin', 'Harmen', 2);// alert the value of the cookie named 'admin'alert (cookiejar.fetch('admin'));// remove the cookiecookiejar.crumble('admin');- Download this code: /code/subcookies2.txt
Access to subcookies
The principle behind subcookies is simple: store multiple values in one cookie. That way, you can store more data without exceeding the browser limit of 20 cookies per domain or server.
It's important to separate your name/value pairs with certain custom characters (characters that are unlikely to appear in a cookie's value). For instance, let's look at these cookies:
admin_name=Harmenadmin_age=22admin_homepage=whatstyle.net- Download this code: /code/subcookies3.txt
If we use subcookies to store this data, our cookie could look like this:
admin=name:Harmen/age:22/homepage:whatstyle.net- Download this code: /code/subcookies4.txt
Notice I use a colon (":") as the name/value separator, and a slash as the subcookie separator ("/").
Now I can store as much data as I'd like, unrestricted by the browser's cookie limit!
Drawbacks
Before looking at the subcookiejar object, there are some things to keep in mind when using subcookies. First, domains (or servers) are only allowed to store 4KB of data (4096 characters). Yes, you could save all your data inside one cookie, but don't overdo it.
Second, some care must be taken in picking separating characters. In the cookies.js file you can download at the bottom of this page, I use $$:$$ as a name/value separator and $$/$$ as the subcookie separator. These character combinations are highly unlikely to be found inside actual cookie values. Always think about your separators. A separator which appears inside your cookie data will split up the value. Consider, for instance, this cookie:
admin_homepage=http://www.whatstyle.net- Download this code: /code/subcookies5.txt
If I were to use the slash and colon mentioned above, the value would break on the "http://" prefix.
The subcookiejar object
The subcookiejar object sports the same bake, fetch and crumble methods the cookiejar object does, but they take different parameters.
bake (cookieName,subcookieObj,days,path)- Sets a new cookie, subcookie-style.
cookieName- The name of the cookie
subcookieObj- An object which members represent the subcookie's name. The value of that member will be the value of the subcookie.
days- The days (as an integer) after which the cookie will expire.
path- The path that has access to this cookie.
fetch (cookieName,subcookieName)- The
fetchmethod fetches the value of the subcookie namedsubcookieNameinside cookiecookieName. crumble (cookieName,subcookieName,days,path)- Unfortunately, crumbling a given subcookie works different from crumbling a regular cookie. It loops through all the values inside the given cookie (named
cookieName), until it finds the subcookie namedsubcookieName. It removes this subcookie from the data and creates a new cookie containing all other name/value pairs present in the cookie. Therefore, you have also have to providedaysandpathparameters, which, naturally, function in the same way as they do in thebakemethod. Note that you can delete the entire cookie withcookiejar.crumble
That's all there is to it! You can access the separators through subcookiejar.subcookieSeparator and subcookiejar.nameValueSeparator if you'd like to change those.
Example:
// create the 'cookie' objectvar c = {name : 'Harmen',age : 22,homepage : http://www.whatstyle.net};// create the cookiesubcookiejar.bake ('admin', c, 2);// alert the subcookie 'name'alert (subcookiejar.fetch('name'));// crumble only the subcookie 'age'subcookiejar.crumble ('admin','age',2);// crumble entire cookiecookiejar.crumble('admin');- Download this code: /code/subcookies6.txt
Download the file
You can download the entire cookies.js file and use it freely. Do leave a comment and tell me what you think of this technique, or tell me how I can improve it.
Filed under Javascript
- ← previous article: Installing PHPEclipse on Ubuntu Feisty Fawn
- → next article: Subcookies, the PHP version
Comments:
This little script is made of awesome. Exactly the kind of thing I was looking for, and very elegantly accomplished. Thanks!
Great script. I did make one change in subcookie.fetch. After getting the cookie value, I check to make sure it was actually found before looking for the subcookie because I was getting an error if none was found:
var cookieValue = cookiejar.fetch(cookieName);
//make sure a cookie was found than proceed
if(cookieValue)
{
var subcookies = cookieValue.split(subcookiejar.subcookieSeparator);
for (var i=0; i<subcookies.length; i++)
{
var sc = subcookies[i].split(subcookiejar.nameValueSeparator);
if (sc[0]==subcookieName) return sc[1];
}
}
return null;
this comment has been quoted by Harmen Janssen
Jim, that's a good change, I didn't think of that.
Glad you like it :)
instead of "/" you can build the whole cookie value as pairs using just ":". this is how i did it and while you still have one char you hope nobody wants to use in their value, it's the fewest possible.
I find very intersting this approach to manage cookies, but:
when you create the subcookie its value will override the existent value stored in the main cookie... :(
Is this normal? I mean, is this how it is supposed to happen?
Shouldn't the subcookie value be added in the main cookie without overriding the original value?
Thank you in advance. :)
this comment has been quoted by Harmen Janssen
Hmm, I see what you mean.
For now; try and fetch the existing subcookies, construct an object including the new subcookies you wish to append and overwrite the existing cookie.
I will rewrite the code to fix the problem in the near future. Keep an eye on your RSS reader :)
I sure will! :)
Thank you very much for your fast response!
Any news about this script?
I really would like to incorporate it in some of my personal projects.