Skip to content

Instantly share code, notes, and snippets.

@ded
Created June 2, 2011 01:17

Revisions

  1. ded created this gist Jun 2, 2011.
    241 changes: 241 additions & 0 deletions jaaulde-cookies.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,241 @@
    /**
    * Copyright (c) 2005 - 2011, James Auldridge
    * All rights reserved.
    *
    * Licensed under the BSD, MIT, and GPL (your choice!) Licenses:
    * http://code.google.com/p/cookies/wiki/License
    *
    */
    var cookies = function() {
    var assembleOptionsString, parseCookies, constructor, defaultOptions = {
    expiresAt: null,
    path: '/',
    domain: null,
    secure: false
    };

    /**
    * resolveOptions - receive an options object and ensure all options are present and valid, replacing with defaults where necessary
    *
    * @access private
    * @static
    * @parameter Object options - optional options to start with
    * @return Object complete and valid options object
    */
    function resolveOptions(options) {
    var returnValue, expireDate;

    if (typeof options !== 'object' || options === null) {
    return defaultOptions;
    }
    returnValue = {
    expiresAt: defaultOptions.expiresAt,
    path: defaultOptions.path,
    domain: defaultOptions.domain,
    secure: defaultOptions.secure
    };

    if (typeof options.expiresAt === 'object' && options.expiresAt instanceof Date) {
    returnValue.expiresAt = options.expiresAt;
    }
    else if (typeof options.hoursToLive === 'number' && options.hoursToLive !== 0) {
    expireDate = new Date();
    expireDate.setTime( expireDate.getTime() + ( options.hoursToLive * 60 * 60 * 1000 ) );
    returnValue.expiresAt = expireDate;
    }

    if (typeof options.path === 'string' && options.path !== '') {
    returnValue.path = options.path;
    }

    if (typeof options.domain === 'string' && options.domain !== '') {
    returnValue.domain = options.domain;
    }

    if (options.secure === true) {
    returnValue.secure = options.secure;
    }

    return returnValue;
    };


    /**
    * assembleOptionsString - analyze options and assemble appropriate string for setting a cookie with those options
    *
    * @access private
    * @static
    * @parameter options OBJECT - optional options to start with
    * @return STRING - complete and valid cookie setting options
    */
    function assembleOptionsString(options) {
    options = resolveOptions(options);
    return (
    ( typeof options.expiresAt === 'object' && options.expiresAt instanceof Date ? '; expires=' + options.expiresAt.toGMTString() : '' ) +
    '; path=' + options.path +
    ( typeof options.domain === 'string' ? '; domain=' + options.domain : '' ) +
    ( options.secure === true ? '; secure' : '' )
    );
    }


    /**
    * parseCookies - retrieve document.cookie string and break it into a hash with values decoded and unserialized
    *
    * @access private
    * @static
    * @return OBJECT - hash of cookies from document.cookie
    */
    function parseCookies() {
    var cookies = {}, i, pair, name, value, separated = document.cookie.split( ';' ), unparsedValue;
    for (i = 0; i < separated.length; i++) {
    pair = separated[i].split( '=' );
    name = pair[0].replace( /^\s*/, '' ).replace( /\s*$/, '' );
    try {
    value = decodeURIComponent( pair[1] );
    } catch(e1) {
    value = pair[1];
    }
    if (typeof JSON === 'object' && JSON !== null && typeof JSON.parse === 'function') {
    try {
    unparsedValue = value;
    value = JSON.parse( value );
    } catch( e2 ) {
    value = unparsedValue;
    }
    }
    cookies[name] = value;
    }
    return cookies;
    }

    function constructor(){}

    /**
    * get - get one, several, or all cookies
    *
    * @access public
    * @paramater Mixed cookieName - String:name of single cookie; Array:list of multiple cookie names; Void (no param):if you want all cookies
    * @return Mixed - Value of cookie as set; Null:if only one cookie is requested and is not found; Object:hash of multiple or all cookies (if multiple or all requested);
    */
    constructor.prototype.get = function (cookieName) {
    var returnValue, item, cookies = parseCookies();

    if (typeof cookieName === 'string') {
    returnValue = ( typeof cookies[cookieName] !== 'undefined' ) ? cookies[cookieName] : null;
    } else if (typeof cookieName === 'object' && cookieName !== null) {
    returnValue = {};
    for (item in cookieName) {
    if (typeof cookies[cookieName[item]] !== 'undefined') {
    returnValue[cookieName[item]] = cookies[cookieName[item]];
    } else {
    returnValue[cookieName[item]] = null;
    }
    }
    } else {
    returnValue = cookies;
    }
    return returnValue;
    };


    /**
    * filter - get array of cookies whose names match the provided RegExp
    *
    * @access public
    * @paramater Object RegExp - The regular expression to match against cookie names
    * @return Mixed - Object:hash of cookies whose names match the RegExp
    */
    constructor.prototype.filter = function (cookieNameRegExp) {
    var cookieName, returnValue = {}, cookies = parseCookies();

    if (typeof cookieNameRegExp === 'string') {
    cookieNameRegExp = new RegExp( cookieNameRegExp );
    }

    for (cookieName in cookies) {
    if (cookieName.match(cookieNameRegExp)) {
    returnValue[cookieName] = cookies[cookieName];
    }
    }
    return returnValue;
    };


    /**
    * set - set or delete a cookie with desired options
    *
    * @access public
    * @paramater String cookieName - name of cookie to set
    * @paramater Mixed value - Any JS value. If not a string, will be JSON encoded; NULL to delete
    * @paramater Object options - optional list of cookie options to specify
    * @return void
    */
    constructor.prototype.set = function (cookieName, value, options) {
    if (typeof options !== 'object' || options === null) {
    options = {};
    }
    if (typeof value === 'undefined' || value === null) {
    value = '';
    options.hoursToLive = -8760;
    } else if( typeof value !== 'string') {
    if (typeof JSON === 'object' && JSON !== null && typeof JSON.stringify === 'function') {
    value = JSON.stringify( value );
    } else {
    throw new Error( 'cookies.set() received non-string value and could not serialize.');
    }
    }
    var optionsString = assembleOptionsString( options );
    document.cookie = cookieName + '=' + encodeURIComponent(value) + optionsString;
    };


    /**
    * del - delete a cookie (domain and path options must match those with which the cookie was set; this is really an alias for set() with parameters simplified for this use)
    *
    * @access public
    * @paramater MIxed cookieName - String name of cookie to delete, or Bool true to delete all
    * @paramater Object options - optional list of cookie options to specify ( path, domain )
    * @return void
    */
    constructor.prototype.del = function (cookieName, options) {
    var allCookies = {}, name;

    if (typeof options !== 'object' || options === null) {
    options = {};
    }

    if (typeof cookieName === 'boolean' && cookieName === true) {
    allCookies = this.get();
    } else if( typeof cookieName === 'string' ) {
    allCookies[cookieName] = true;
    }

    for (name in allCookies) {
    if (typeof name === 'string' && name !== '') {
    this.set( name, null, options );
    }
    }
    };

    /**
    * setOptions - set default options for calls to cookie methods
    *
    * @access public
    * @param Object options - list of cookie options to specify
    * @return void
    */
    constructor.prototype.setOptions = function (options) {
    if (typeof options !== 'object') {
    options = null;
    }

    defaultOptions = resolveOptions( options );
    };

    return new constructor();
    }();

    if (typeof module !== 'undefined' && module.exports) {
    module.exports.cookies = cookies;
    }