Skip to content

Instantly share code, notes, and snippets.

@rmcvey
Last active December 12, 2015 06:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rmcvey/4731847 to your computer and use it in GitHub Desktop.
Save rmcvey/4731847 to your computer and use it in GitHub Desktop.
/**
* 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