UNPKG

shelf.js

Version:

A modular, powerful wrapper library for persistent objects in the browser and Node.js

318 lines (263 loc) 8.84 kB
/** * ## Cookie storage for Shelf.js * Copyright 2014 Stefano Balietti * * Original library from: * See http://code.google.com/p/cookies/ */ (function(exports) { var store = exports.store; if (!store) { throw new Error('cookie.shelf.js: shelf.js core not found.'); } if ('undefined' === typeof window) { throw new Error('cookie.shelf.js: window object not found.'); } var cookie = (function() { var resolveOptions, assembleOptionsString, parseCookies, constructor; var 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 */ resolveOptions = function(options){ var returnValue, expireDate; if(typeof options !== 'object' || options === null){ returnValue = defaultOptions; } else { 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 */ assembleOptionsString = function (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 */ parseCookies = function() { var cookies = {}, i, pair, name, value, separated = document.cookie.split(';'), unparsedValue; for(i = 0; i < separated.length; i = i + 1){ pair = separated[i].split('='); name = pair[0].replace(/^\s*/, '').replace(/\s*$/, ''); try { value = decodeURIComponent(pair[1]); } catch(e1) { value = pair[1]; } // if (JSON && 'object' === typeof JSON && 'function' === typeof JSON.parse) { // try { // unparsedValue = value; // value = JSON.parse(value); // } // catch (e2) { // value = unparsedValue; // } // } cookies[name] = store.parse(value); } return cookies; }; constructor = function(){}; /** * 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 store.stringify === 'function') { // // value = JSON.stringify(value); // } // else { // throw new Error('cookies.set() received non-string value and could not serialize.'); // } value = store.stringify(value); } 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); } } }; /** * test - test whether the browser is accepting cookies * * @access public * @return Boolean */ constructor.prototype.test = function() { var returnValue = false, testName = 'cT', testValue = 'data'; this.set(testName, testValue); if(this.get(testName) === testValue) { this.del(testName); returnValue = true; } return returnValue; }; /** * 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 cookies are supported by the browser if (cookie.test()) { store.addType("cookie", function(key, value, options) { if ('undefined' === typeof key) { return cookie.get(); } if ('undefined' === typeof value) { return cookie.get(key); } // Set to NULL means delete if (value === null) { cookie.del(key); return null; } return cookie.set(key, value, options); }); } }(this));