Skip to content

Instantly share code, notes, and snippets.

@orion110217
Last active June 9, 2020 21:00
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 orion110217/ef26968000df7290de03a8f774b46b79 to your computer and use it in GitHub Desktop.
Save orion110217/ef26968000df7290de03a8f774b46b79 to your computer and use it in GitHub Desktop.
Polyfills localStorage and sessionStorage when cookies are disabled.
const hasLocalStorage = (function(){
try {
localStorage.setItem('mod', 'mod');
localStorage.removeItem('mod');
return true;
} catch(e) {
return false;
}
})()
if (!hasLocalStorage) {
(function () {
var Storage = function (type) {
function createCookie(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=/";
}
function readCookie(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;
}
function setData(data) {
// Convert data into JSON and encode to accommodate for special characters.
data = encodeURIComponent(JSON.stringify(data));
// Create cookie.
if (type == 'session') {
createCookie(getSessionName(), data, 365);
} else {
createCookie('localStorage', data, 365);
}
}
function clearData() {
if (type == 'session') {
createCookie(getSessionName(), '', 365);
} else {
createCookie('localStorage', '', 365);
}
}
function getData() {
// Get cookie data.
var data = type == 'session' ? readCookie(getSessionName()) : readCookie('localStorage');
// If we have some data decode, parse and return it.
return data ? JSON.parse(decodeURIComponent(data)) : {};
}
function getSessionName() {
// If there is no name for this window, set one.
// To ensure it's unquie use the current timestamp.
if(!window.name) {
window.name = new Date().getTime();
}
return 'sessionStorage' + window.name;
}
// Initialise if there's already data.
var data = getData();
return {
length: 0,
clear: function () {
data = {};
this.length = 0;
clearData();
},
getItem: function (key) {
return data[key] === undefined ? null : data[key];
},
key: function (i) {
// not perfect, but works
var ctr = 0;
for (var k in data) {
if (ctr == i) return k;
else ctr++;
}
return null;
},
removeItem: function (key) {
delete data[key];
this.length--;
setData(data);
},
setItem: function (key, value) {
data[key] = value+''; // forces the value to a string
this.length++;
setData(data);
}
};
};
// Replace window.localStorage and window.sessionStorage with out custom
// implementation.
var localStorage = new Storage('local');
var sessionStorage = new Storage('session');
Object.defineProperty(window, "localStorage", { value: localStorage })
Object.defineProperty(window, "sessionStorage", { value: sessionStorage })
})();
}
@puzzfuzz
Copy link

puzzfuzz commented Jan 9, 2018

FYI this does not cover all cases - I'm seeing TypeError: Attempting to change access mechanism for an unconfigurable property. at line 120 for Safari 9.x in our monitoring systems.

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