Last active
December 12, 2015 06:48
-
-
Save rmcvey/4731847 to your computer and use it in GitHub Desktop.
This file contains 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
/** | |
* I wrote a much more robust storage facade called jsper <https://github.com/rmcvey/jsper>, this is more lightweight | |
* javascript html5 storage wrapper with fallback to cookies | |
* @author Rob McVey | |
* @license MIT License | |
*/ | |
var storage = ( function( context ) { | |
// just use cookies if not HTML5 | |
var fallback; | |
// create cookieStorage engine if browser is not HTML5 | |
if( fallback =! ( 'localStorage' in context ) ) { | |
window.cookieStorage = ( function() { | |
var that = this, i = 0, prefix = 'storage_key_'; | |
// Initialize by splitting the array of Cookies | |
var cookies = document.cookie.split( '; ' ); | |
for ( ; i < cookies.length; i++ ) { | |
var pair = cookies[i].split( '=' ); | |
that[pair[0]] = pair[1]; | |
} | |
return { | |
// Create Function: Pass name of cookie, value, and days to expire | |
setItem: function ( name, value, days ) { | |
if ( days ) { | |
var date = new Date(); | |
date.setTime(date.getTime()+(days*24*60*60*1000)); | |
var expires = "; expires="+date.toGMTString(); | |
} else { | |
var expires = ""; | |
} | |
if ( value.indexOf('"') !== -1 ) { | |
value = escape(value); | |
} | |
if ( value.length > 4000 ) return false; // die if the cookie is too big | |
document.cookie = prefix+name+"="+value+expires+"; path=/"; | |
that[name] = value; | |
}, | |
getItem: function( name ) { | |
return (prefix+name) in that ? unescape(that[ prefix+name ]) : null; | |
}, | |
// Erase cookie by name | |
removeItem: function ( name ) { | |
that.setItem(name,'',-1); | |
that[name] = undefined; | |
} | |
} | |
})(); | |
} | |
// this scope will not be accessible once the containing function returns, i.e. private scope | |
var _store = function( engine, key, value ) { | |
fallback && ( engine = 'cookieStorage' ); | |
if ( typeof value !== 'undefined' && value ) { | |
value = JSON.stringify( value ); | |
return context[engine].setItem( key, value ); | |
} | |
return JSON.parse( context[engine].getItem( key ) ) || null; | |
} | |
var _remove = function( key ) { | |
var i = 0, engines = ['localStorage', 'cookieStorage', 'sessionStorage']; | |
for( ; i < engines.length; i++ ) { | |
try{ | |
var engine = engines[i]; | |
context[engine].removeItem( key ); | |
} catch(e){ } // don't care about this error | |
} | |
} | |
// the scope of the object returned retains access to the function scope | |
return { | |
session: function( key, value ) { | |
return _store( 'sessionStorage', key, value ); | |
}, | |
persistent: function( key, value ) { | |
return _store( 'localStorage', key, value ); | |
}, | |
erase: function( key ) { | |
_remove( key ); | |
return this; | |
}, | |
each: function( key, callback, engine ) { | |
// default value for storage engine | |
engine = engine || 'localStorage'; | |
// ensure a valid value was passed, return if not | |
if ( ['localStorage', 'sessionStorage'].indexOf( engine ) === -1 ) return false; | |
var data = _store( engine, key, undefined ); | |
// no need to iterate over the object if the callback passed is not a function | |
if ( typeof callback === 'function' && data ) { | |
// data is an array | |
if ( 'splice' in data ) { | |
// loop over array and apply callback to each item | |
for( var i = 0; i < data.length; i++ ) { | |
var current_record = data[i]; | |
// though we could use the syntax: callback( data ), I prefer to additionally provide access to the data in `this` | |
// check the usage examples for how this looks when calling the each method | |
callback.apply( current_record, [ current_record, i ] ); | |
} | |
} else { | |
// loop over object and apply callback to each item | |
for( var attribute in data ) { | |
// now I am passing the value @index as well as the name of the attribute to the callback | |
callback.apply( data[attribute], [ data[attribute], attribute ] ); | |
} | |
} | |
} | |
return this; | |
} | |
}; | |
})( window ); | |
// examples | |
var user1 = { first_name: 'Rob', city: 'St. Louis' }, | |
user2 = { first_name: 'Jeb', city: 'Nashville' } | |
storage.persistent( 'user', user1 ); | |
storage.persistent( 'users', [ user1, user2 ]); | |
storage.each( 'user', function( item, index ) { | |
console.log( "%s => %s", index, item ); | |
}); | |
storage.each( 'users', function( item, index ) { | |
console.log( "%s => { %s | %s }", index, this.first_name, item.city ); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment