andy-h
2/7/2014 - 2:15 PM

Methods for working with cookies

Methods for working with cookies

//If cookies are not supported by the browser, `Cookies` will be undefined

//Cookies.set(name, value[, options])
// creates, modifies, or removes a cookie
// `options` may be an object including `expires`, `path`, `domain`, and/or `secure`
// `options.expires` can be either a Date object or the number of seconds until it should expire
//  (0 or undefined indicates end of session, <0 removes the cookie, Infinity sets it to 50 years)
//
//Cookies.get(name)
// returns the value of the first cookie with that name
//
//Cookies.getAll([name])
// if no name is specified, returns an array of all name/value pairs (each pair is an object {name, value})
// if a name is specified, returns an array of values of all cookies with that name
// this can be especially useful when there is more than one cookie with the same name (i.e., if it's been
//  set for multiple paths or domains)
//
//Cookies.erase(name[, options])
// removes a cookie
// `options` may be an object including `path` and/or `domain`

var Cookies = (function(){
	
	"use strict";
	
	//options.expires can be either a Date object or the number of seconds until it should expire
	// e.g.: 60: 1 minute from now
	//		 0: end of session
	//		 -1: remove cookie
	function setCookie(name, value, options){
		var expires, path, domain, secure, expiration, date;
		if(!name && name!==0) return false;
		if(typeof(value) === "undefined" || value === null) return false;
		options = options || {};
		
		expiration = "";
		if(options.expires){
			expires = options.expires;
			if(expires.toUTCString) expiration = expires.toUTCString();	//expires on given Date
			else if(!isNaN(expires)){	//expires in given number of seconds
				if(expires===Infinity) expires = 1576800000;	//50 years
				else if(expires===-Infinity) expires = -1;
				date = new Date();
				date.setTime(date.getTime()+(expires*1000));
				expiration = date.toUTCString();
			}
			//else expires at end of session
		}
		//else expires at end of session
		
		expiration = expiration ? "; expires="+expiration : "";
		path = options.path ? "; path=" + encode(options.path) : "";
		domain = options.domain ? "; domain="+encode(options.domain) : "";
		secure = options.secure ? "; secure" : "";
		document.cookie = encodeURIComponent(name)+"="+encodeURIComponent(value)+expiration+path+domain+secure;
		
		return true;
	}
	
	//Returns the value of the cookie with the provided name
	//If there are multiple cookies with the same name (i.e., if it's been set for multiple paths or domains), it only returns the first match
	function getCookie(name){
		var rxp, m;
		if(!name && name!==0) return null;
		name = (encodeURIComponent(name)).replace(/[.*+?^=!:${}()|[\]\/\\]/g, "\\$&");	//escape regexp characters
		rxp = new RegExp("(?:^|;)\\s*"+name+"=([^;]*)");
		m = rxp.exec(document.cookie);
		return m ? decodeURIComponent(m[1]) : null;
	}
	
	//If no name is specified, returns an array of all name/value pairs (each pair is an object {name, value})
	//If a name is specified, returns an array of values of all cookies with that name
	//This can be especially useful when there is more than one cookie with the same name (i.e., if it's been
	// set for multiple paths or domains).
	//Note that which cookies are returned and in what order depends on the browser, so it's impossible to determine which
	// instance of a name corresponds to which path or domain.
	function getAllCookies(name){
		var m, result = [], rxp;
		if(!name && name!==0){	//name is not specified, return name/value pairs of all cookies
			rxp = new RegExp("(?:^|;)\\s*([^=]*)=([^;]*)", "g");
			while(m = rxp.exec(document.cookie)){
				result.push( { name: decodeURIComponent(m[1]), value: decodeURIComponent(m[2]) } );
			}
		}
		else{	//name is specified; return values of all cookies with that name
			name = (encodeURIComponent(name)).replace(/[.*+?^=!:${}()|[\]\/\\]/g, "\\$&");	//escape regexp characters
			rxp = new RegExp("(?:^|;)\\s*"+name+"=([^;]*)", "g");
			while(m = rxp.exec(document.cookie)){
				result.push(decodeURIComponent(m[1]));
			}
		}
		return result;
	}
	
	function eraseCookie(name, options){
		options = options || {};
		return setCookie(name, "", {expires:-1, path:options.path, domain:options.domain});
	}
	
	function encode(str){ return String(str).replace(/%/g, "%25").replace(/;/g, "%3B").replace(/=/g, "%3D"); }
	function decode(str){ return String(str).replace(/%3D/g, "=").replace(/%3B/g, ";").replace(/%25/g, "%"); }
	
	function testSupport(){
		var check;
		if(getCookie("test_cookie_support") !== null) return true;
		setCookie("test_cookie_support", "test");
		check = getCookie("test_cookie_support");
		eraseCookie("test_cookie_support");
		return !!check;
	}
	
	if(testSupport()){	//cookies are supported
		return {
			set: setCookie,
			get: getCookie,
			getAll: getAllCookies,
			erase: eraseCookie,
		};
	}
	//else cookies are not supported; return undefined
	
})();