Created
July 24, 2013 23:51
-
-
Save edeviant/6075682 to your computer and use it in GitHub Desktop.
Module for custom interface around local storage options. Handles failover to cookie (via modified shim). Exposes generic handlers for storing, retrieving, and removing by data type or by straight key/value. Maintains reference data as saved/retrieved.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Cars.com Stash Module | |
* @version AMD 1.0 | |
* @module modules/common/stash | |
* Provides a facade around local storage functionality | |
* - ensures a technology agnostic approach | |
* - ensure standard interface for storage crud | |
*/ | |
define([], function() { | |
/** initialize global namespace if not available */ | |
window.CARS = window.CARS || {}; | |
CARS.debugStack = CARS.debugStack || []; | |
CARS.pushDebug = CARS.pushDebug || function() { | |
var args = Array.prototype.slice.call(arguments); | |
CARS.debugStack.push(new Date().toLocaleTimeString() +': '+ args.join(' ')); | |
}; | |
CARS.dumpDebug = CARS.dumpDebug || function() { | |
for (var i=0,j=CARS.debugStack.length; i<j; i++) { | |
console.log(CARS.debugStack[i]); | |
} | |
CARS.debugStack = []; | |
}; | |
var Storage = function(options) { | |
CARS.pushDebug('===== init [stash] module v1.0 ====='); | |
// this.id = Math.floor(Math.random()*1000); | |
var cookieOnly = options.cookieOnly || false; | |
var storageCookieName = options.storageCookieName || "carsLocalStorage"; | |
var id = Math.floor(Math.random()*1000); | |
this.cookieBased = cookieOnly; | |
/** | |
* returns the handle to LocalStorage or equivalent | |
* - supports failover for when localstorage is not available | |
* - adopted from https://gist.github.com/remy/350433 | |
* @return {object} ability to use local storage | |
*/ | |
var initStash = function(cookieName, cookieOnly) { | |
var stash = null; | |
/** | |
* presence of Local Storage capability | |
* @public | |
* @return {boolean} ability to use local storage | |
*/ | |
var checkForLS = function() { | |
return navigator.cookieEnabled && 'localStorage' in window && window['localStorage'] !== null; | |
}; | |
if (checkForLS() && !cookieOnly) { | |
CARS.pushDebug('[stash]', 'create localStorage-based stash'); | |
stash = { | |
"persist": window.localStorage, | |
"session": window.sessionStorage, | |
"cookieBased": false, | |
id: Math.floor(Math.random()*1000) | |
}; | |
} else { | |
/* create alternative that mirrors LS functionality | |
* cookie only failover (for now) | |
*/ | |
var genStash = function(type) { | |
var length = 0, data = null; | |
createCookie = function(name, value, days) { | |
var date, expires; | |
if (days) { | |
date = new Date(); | |
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); | |
expires = "; expires=" + date.toGMTString(); | |
} else { | |
expires = ""; | |
} | |
document.cookie = name + "=" + value + expires + "; path=/"; | |
}; | |
readCookie = function(name) { | |
var nameEQ = name + "=", | |
ca = document.cookie.split(';'), | |
i, c; | |
for (i = 0; i < ca.length; i++) { | |
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; | |
}; | |
var Storage = function() { | |
var id = Math.floor(Math.random()*1000); | |
var setData = function(data) { | |
data = JSON.stringify(data); | |
if (type == 'session') { | |
window.name = data; | |
} else { | |
createCookie(cookieName, data, 365); | |
} | |
}; | |
var clearData = function() { | |
if (type == 'session') { | |
window.name = ''; | |
} else { | |
createCookie(cookieName, '', 365); | |
} | |
}; | |
var getData = function() { | |
var data = (type == 'session') ? window.name : readCookie(cookieName); | |
if (data) { | |
try { | |
data = JSON.parse(data); | |
} catch(e) {} | |
} | |
return data || {}; | |
}; | |
// initialize if there's already data | |
var data = getData(); | |
this.clear = function() { | |
data = {}; | |
length = 0; | |
clearData(); | |
}; | |
this.getItem = function(key) { | |
return data[key] === undefined ? null : data[key]; | |
}; | |
this.key = function(i) { | |
// not perfect, but works | |
var ctr = 0; | |
for(var k in data) { | |
if(ctr == i) return k; | |
else ctr++; | |
} | |
return null; | |
}; | |
this.keys = function() { | |
}; | |
this.removeItem = function(key) { | |
delete data[key]; | |
length--; | |
setData(data); | |
}; | |
this.setItem = function(key, value) { | |
data[key] = value + ''; // force value to a string | |
length++; | |
setData(data); | |
}; | |
}; | |
return new Storage(); | |
}; | |
CARS.pushDebug('[stash]', 'create cookie-based stash'); | |
stash = { | |
"persist": new genStash('local'), | |
"session": new genStash('session'), | |
"cookieBased": true, | |
"id": Math.floor(Math.random()*1000) | |
}; | |
} | |
return stash; | |
}; | |
var myStash = initStash(storageCookieName, cookieOnly); | |
/** | |
* update the local last saved value | |
* - effectively meta update date | |
* @return {null} | |
*/ | |
var updateWhenLastStashed = function() { | |
myStash.session.setItem('lastUpdate', new Date().getTime()); | |
}; | |
/** | |
* boolean of if we are using actual local storage | |
* @return {boolean} using local storage? | |
*/ | |
this.isLocalStorage = function() { | |
return myStash.checkForLS(); | |
}; | |
/** | |
* accepts a payload to store in the local stash | |
* @return {[type]} [description] | |
*/ | |
this.addToStash = function(key, data, trackUpdate) { | |
CARS.pushDebug('[stash]', 'adding',key,'to stash'); | |
myStash.persist.setItem(key, JSON.stringify(data)); | |
updateWhenLastStashed(); | |
}; | |
this.getFromStash = function(key) { | |
return JSON.parse(myStash.persist.getItem(key)); | |
}; | |
/** | |
* TODO: MAKE THIS LESS DANGEROUS | |
* clears all stashed data | |
* does not remove any data from server | |
* @return {boolean} success or failure | |
*/ | |
this.clearAll = function() { | |
myStash.persist.clear(); | |
myStash.session.clear(); | |
updateWhenLastStashed(); | |
}; | |
/** | |
* get the time of the last saved asset | |
* @return {???} some representaion of time | |
*/ | |
this.getWhenLastStashed = function() { | |
return myStash.persist.getItem('lastUpdate'); | |
}; | |
/** | |
* interface to storing data for a user's profile | |
* @param {string} type type of asset to save (enum) | |
* @param {object} criteria hash of data to stash/store | |
* @param {boolean} persist stash persistent (default true) | |
* @param {boolean} store persist to server store (default true) | |
* @return {boolean} success or failure | |
*/ | |
this.saveAsset = function(type, criteria, persist, store) { | |
CARS.pushDebug('[stash]', 'adding',type,'to stash'); | |
var typeData; | |
criteria.id = criteria.id || Math.floor(Math.random()*10000); | |
persist = persist || true; | |
store = store || persist || true; | |
typeData = this.getFromStash(type) || []; | |
typeData.push(criteria.id); | |
this.addToStash(type, typeData); | |
this.addToStash(type+':'+criteria.id, criteria); | |
if (store) { | |
// console.log('push to CPS.loc ', CPS.loc); | |
} | |
updateWhenLastStashed(); | |
return true; | |
}; | |
/** | |
* interface to getting data for a user's profile | |
* - fails over to store if not in stash | |
* @param {string} type type of asset to save (enum) | |
* @param {boolean} persist stash persistent (default true) | |
* @param {boolean} store persist to server store (default true) | |
* @return {boolean} success or failure | |
*/ | |
this.getAssets = function(type, persist) { | |
var typeData, data = []; | |
// check stash | |
typeData = this.getFromStash(type) || []; | |
if (typeData) { | |
// loop to get records | |
for (var i = typeData.length - 1; i >= 0; i--) { | |
data.push(this.getFromStash(type+':'+typeData[i])); | |
} | |
} | |
return data; | |
}; | |
}; | |
return Storage; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment