Skip to content

Instantly share code, notes, and snippets.

@ksafranski
Last active February 26, 2026 06:14
Show Gist options
  • Select an option

  • Save ksafranski/4718380 to your computer and use it in GitHub Desktop.

Select an option

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
Copy Markdown

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

@devalf

devalf commented Feb 3, 2015

Copy link
Copy Markdown

This is great. Thanks!

@luigi37

luigi37 commented May 15, 2015

Copy link
Copy Markdown

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;

}

@m-rd-r

m-rd-r commented Sep 9, 2015

Copy link
Copy Markdown

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

@NewWorldOrderly

NewWorldOrderly commented Apr 21, 2016

Copy link
Copy Markdown

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

lfbn commented Jul 25, 2016

Copy link
Copy Markdown

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

rw3iss commented Sep 29, 2016

Copy link
Copy Markdown

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
Copy Markdown

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

@danicholls

Copy link
Copy Markdown

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

zlatan1981 commented Sep 13, 2017

Copy link
Copy Markdown

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
Copy Markdown

Awesome! Thanks!

@Download

Copy link
Copy Markdown
 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