Page 1 of 1

Cutting Cookies Rate Topic: -----

#1 andrewsw  Icon User is online

  • Fire giant boob nipple gun!
  • member icon

Reputation: 3370
  • View blog
  • Posts: 11,419
  • Joined: 12-December 12

Posted 10 February 2013 - 08:15 AM

document.cookie is an odd beast. When output it appears as a long string, with different parts separated by semi-colons. For example,

console.log(document.cookie);
"IGTP=LI=1:LM=1342948343; 
MPRF=H4sIAAAAAAAAAKt4vW_a6ctqXUwMk5gUUpINjY2TE9OMDNPSks2Sk9LMjZNTTgwnMDMAAFT5Vl0wAAAA; 
OGPERM=W6%3D0.0.1.63; APISID=i4TGNQxpIG5vDbjv/ALlKau5J1DI1u3-hS; 
PREF=ID=17a45ffe3c6d5:U=2e3e90464cb0:LD=en:TM=1327346305:LM=135771:GM=1:IG=1:SG=1:S=tICH03uJPV"



When we create a cookie we assign to document.cookie like this:

document.cookie = 'cookie1=testvalue; expires=Thu, 2 Aug 2001 20:47:11 UTC; path=/'

If it were a simple object or string we would expect this assignment to wipe-out all the other values?! Notice also, that when we output the cookie it displays only the cookie-names and values; the other information (expires, path) is not accessible to us.

In order to read the value of a cookie we need to split the cookie "string" at the semi-colons, and loop through the resultant array. Here's a typical example:

quirksmode
function readCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    }
    return null;
}


There is not a delete() method for a cookie. To achieve the deletion we re-create the cookie, setting its expiry to a date either in the past or, perhaps, a few seconds into the future:
s
function eraseCookie(name) {
    createCookie(name,"",-1);
}


Confusingly as well, document.cookie is singular, but we store a number of (single) cookies in it?!

*******
I built a search page for myself and I wanted to store certain sites that I would exclude from the search as cookies. But i wanted to store the url-addresses as the cookie-name, and a title or description as the value. Standard cookie-methods didn't allow for searching by 'name', and storing the odd characters that might appear in an url could be problematic. So this led me to the use of regular expressions.

Using regular expressions I can treat the cookie as a long string, rather than having to split it apart and loop through the various elements. [There is an overhead involved with the use of Regex, but there is also with splitting and parsing of a (long) string.] With Regex I can make cookies more flexible with the following functions:

cNameExists(cookie_name) // boolean
// (sometimes I just want to check for the existence of a cookie!)
cValueExists(cookie_value) // boolean
cNameGet(cookie_value)
cValueGet(cookie_name)


My approach also gives cookie-names added value. Traditionally, the name is a known quantity. We would sometimes squeeze several values into a single cookie, making up our own separator in the process:

document.cookie = 'cookie1=testvalue#value1; expires=Thu, 2 Aug 2001 20:47:11 UTC'

Again, this means we have to split this and ensure that we always follow the same pattern when creating our cookie(s). With my approach we can store them as separate cookies - because we are able to search by either name or value: the cookie now behaves as a dictionary.

Because I am using regular expressions, and I might be storing strange characters in either the name or value, I make use of the following helper function. This escapes the characters (of my names and values) that have a special meaning to Regex (NB this is only used when applying Regex searches, they are not stored this way):

var escapeReg = function (str) {
    // Helper fn: escapes characters for use with a regular expression.
    return str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
};


This function has utility outside of my cookie methods, and is a candidate for adding to the String prototype. [I cannot take credit for it. I found a couple of examples on the internet and tweaked them a little.]

The tricky thing that remained was to create Regex expressions that would correctly identify the names and values (separately) within the document.cookie.

[Note: encoding the cookies with encodeURIComponent() is a standard approach.]

I also include functions delAllCookies() and cookieStr(), although this second is really only for testing purposes. However, now that both the names and values of cookies have meaning this function could be useful.

var escapeReg = function (str) {
    // Helper fn: escapes characters for use with a regular expression.
    return str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
};

var setCookie = function (name, value, expires, path, domain, secure) {
    // Sets the name/value pair (encoded) - 'expires' is the no. of days.
    var expires_date;
    if (expires) {
        expires_date = new Date();
        expires_date.setDate(expires_date.getDate() + expires);
    }
    document.cookie = encodeURIComponent(name) + "=" + 
        encodeURIComponent(value) +
        ( ( expires ) ? ";expires=" + expires_date.toUTCString() : "" ) +
        ( ( path ) ? ";path=" + path : "" ) +
        ( ( domain ) ? ";domain=" + domain : "" ) +
        ( ( secure ) ? ";secure" : "" );
};

var deleteCookie = function (name, path, domain) {
    // Encodes the name before deleting.
    document.cookie = encodeURIComponent(name) + "=" + 
        ( ( path ) ? ";path=" + path : "") + ( ( domain ) ? ";domain=" + 
            domain : "" ) + ";expires=Fri, 01-Jan-2010 00:00:01 UTC";
    // ..could be any date in the past
};
var delAllCookies = function () {
    var currDate = new Date(), i, theCookie = document.cookie.split(";");
    currDate = currDate.toUTCString();
    i = theCookie.length;
    while ( i-- ) {
        document.cookie = theCookie[i] + "; expires =" + currDate;
    }
};
// the following functions are case-insensitive
var cNameExists = function (cookie_name) {
    var testName, myReg;
    if (document.cookie.length == 0) return false;
    testName = escapeReg(cookie_name);
    myReg = new RegExp('(^|;) ?' + testName + '=([^;]*)(;|$)','i');
    return myReg.test(decodeURIComponent(document.cookie));
};
var cValueExists = function (cookie_value) {
    var testName, myReg;
    if (document.cookie.length == 0) return false; 
    testName = escapeReg(cookie_value);
    myReg = new RegExp('(=)' + testName + '(;|$)','i');
    return myReg.test(decodeURIComponent(document.cookie));
};
var cNameGet = function (cookie_value) {
    var testName, myReg, results;
    if (document.cookie.length == 0) return '';
    testName = escapeReg(cookie_value);
    myReg = new RegExp('(^|;) ?([^=]*)=' + testName + '(;|$)','i');
    results = decodeURIComponent(document.cookie).match(myReg);
    return ( results ) ? results[2] : '';
};
var cValueGet = function (cookie_name) {
    var testName, myReg, results;
    if (document.cookie.length == 0) return '';
    testName = escapeReg(cookie_name);
    myReg = new RegExp('(^|;) ?' + testName + '=([^;]*)(;|$)','i');
    results = decodeURIComponent(document.cookie).match(myReg);
    return ( results ) ? results[2] : '';
};

var cookieStr = function () {
    // Returns a string (with line breaks) which could be 
    // placed in, for example, a textarea.
    return decodeURIComponent(document.cookie).
        replace(/([^=;]+)=([^;]*)[;\s]*/g,'$1 ($2)\n') || '';
};


NB These are all (global) functions. I had originally tucked them away inside an object (a library) but, for the purpose of this tutorial, have extracted them as standalone-functions.

EU cookie law

This post has been edited by andrewsw: 10 February 2013 - 09:42 AM


Is This A Good Question/Topic? 0
  • +

Page 1 of 1