Skip to content

Instantly share code, notes, and snippets.

@ksafranski
Last active July 2, 2022 15:25
Show Gist options
  • Star 67 You must be signed in to star a gist
  • Fork 23 You must be signed in to fork a gist
  • Save ksafranski/4718380 to your computer and use it in GitHub Desktop.
Save ksafranski/4718380 to your computer and use it in GitHub Desktop.
Simple localStorage function with Cookie fallback for older browsers.
/**
* Simple localStorage with Cookie Fallback
* v.1.0.0
*
* USAGE:
* ----------------------------------------
* Set New / Modify:
* store('my_key', 'some_value');
*
* Retrieve:
* store('my_key');
*
* Delete / Remove:
* store('my_key', null);
*/
var store = function store(key, value) {
var lsSupport = false;
// Check for native support
if (localStorage) {
lsSupport = true;
}
// If value is detected, set new or modify store
if (typeof value !== "undefined" && value !== null) {
// Convert object values to JSON
if ( typeof value === 'object' ) {
value = JSON.stringify(value);
}
// Set the store
if (lsSupport) { // Native support
localStorage.setItem(key, value);
} else { // Use Cookie
createCookie(key, value, 30);
}
}
// No value supplied, return value
if (typeof value === "undefined") {
// Get value
if (lsSupport) { // Native support
data = localStorage.getItem(key);
} else { // Use cookie
data = readCookie(key);
}
// Try to parse JSON...
try {
data = JSON.parse(data);
}
catch(e) {
data = data;
}
return data;
}
// Null specified, remove store
if (value === null) {
if (lsSupport) { // Native support
localStorage.removeItem(key);
} else { // Use cookie
createCookie(key, '', -1);
}
}
/**
* Creates new cookie or removes cookie with negative expiration
* @param key The key or identifier for the store
* @param value Contents of the store
* @param exp Expiration - creation defaults to 30 days
*/
function createCookie(key, value, exp) {
var date = new Date();
date.setTime(date.getTime() + (exp * 24 * 60 * 60 * 1000));
var expires = "; expires=" + date.toGMTString();
document.cookie = key + "=" + value + expires + "; path=/";
}
/**
* Returns contents of cookie
* @param key The key or identifier for the store
*/
function readCookie(key) {
var nameEQ = key + "=";
var ca = document.cookie.split(';');
for (var i = 0, max = ca.length; i < max; i++) {
var 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;
}
};
@clearwest
Copy link

Simple + Works = Awesome! Thank you so much :)

@devalf
Copy link

devalf commented Feb 3, 2015

This is great. Thanks!

@luigi37
Copy link

luigi37 commented May 15, 2015

Thanks for this: simple and easy. As per my understanding getItem and setItem work always with string (or null) so I'd suggest to ensure the value returned is a string as well (had some problems with "true" and true (boolean) )

// If value is detected, set new or modify store
if (typeof value !== "undefined" && value !== null) {
    // Convert object values to JSON
    if ( typeof value === 'object' ) {
        value = JSON.stringify(value);
    }
    value2=""+value; //20150515
    // Set the store
    if (lsSupport) { // Native support
        window.localStorage.setItem(key, value2);//20150515
    } else { // Use Cookie
        createCookie(key, value, 30);
    }
}

// No value supplied, return value
if (typeof value === "undefined") {
    // Get value
    if (lsSupport) { // Native support
        data = window.localStorage.getItem(key);
    } else { // Use cookie 
        data = readCookie(key);
    }

    // Try to parse JSON...
    try {
       data = JSON.parse(data);
    }
    catch(e) {
       data = data;
    }
    if (data!=null) {
    data=""+data; //lp20150515
}
    return data;

}

@mderijcke
Copy link

Good work, but don't you think data = data; is a bit redundant? ;-)

@NewWorldOrderly
Copy link

NewWorldOrderly commented Apr 21, 2016

I would replace your IF statement

    // Check for native support
    if (localStorage) {
        lsSupport = true;
    }

with

   function storageAvailable(type) {
        try {
            var storage = window[type],
                x = '__storage_test__';
            storage.setItem(x, x);
            storage.removeItem(x);
            return true;
        }
        catch(e) {
            return false;
        }
    }
    if (storageAvailable('localStorage')) {
        // Yippee! We can use localStorage awesomeness
        lsSupport = true;
    }

This will allow this to work in Private Browsing mode on iOS Safari

@lfbn
Copy link

lfbn commented Jul 25, 2016

Great Gist!

I would only add a config var. Not really important.

var config = {'cookies': {'expirationDays': 30}};

And the use it, instead of '30' hardcoded:

createCookie(key, value, config.cookies.expirationDays);

@rw3iss
Copy link

rw3iss commented Sep 29, 2016

Need to initialize the 'data' variable inside the second if:
if (typeof value === "undefined") {
var data = null;

Otherwise throws an error that data isn't defined...

Nice gist, thank you !

@prowseed
Copy link

Great, thanks! 👍
Yet, in my opinion @NewWorldOrderly is right about checking support, as I just have had issue with that.

@danicholls
Copy link

Update to @NewWorldOrderly's edit--I ran into a problem where (on FF, local) localStorage.removeItem() would not fire (presumably because it was not completed). Adding a slight delay works:

            setTimeout(function(){ storage.removeItem(x); }, 400);

Here's the whole thing in a gist.

@zlatan1981
Copy link

zlatan1981 commented Sep 13, 2017

Hello,
I am volunteering for a non-profit organization and trying to find some code snippet to provide localstorage service.
This gist is a good fit, just wonder if I can use your code (copy and paste it to our project files)?

Thanks!
Wesley

@BillyHilly
Copy link

Awesome! Thanks!

@Download
Copy link

 setTimeout(function(){ storage.removeItem(x); }, 400);

This looks weird. localStorage methods are all sync. No need to wrap them in timeouts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment