Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 8 years ago.
Improve this question
I'm looking for javascript libraries and code that can simulate localStorage on browsers that do not have native support.
Basically, I'd like to code my site using localStorage to store data and know that it will still work on browsers that don't natively support it. This would mean a library would detect if window.localStorage exists and use it if it does. If it doesn't exist, then it would create some sort of fallback method of local storage, by creating its own implementation in the window.localStorage namespace.
So far, I've found these solutions:
Simple sessionStorage implementation.
An implementation that uses cookies (not thrilled with this idea).
Dojo's dojox.storage, but it is it's own thing, not really a fallback.
I understand that Flash and Silverlight can be used for local storage as well, but haven't found anything on using them as a fallback for standard HTML5 localStorage. Perhaps Google Gears has this capability too?
Please share any related libraries, resources, or code snippets that you've found! I'd be especially interested in pure javascript or jquery-based solutions, but am guessing that is unlikely.
Pure JS based simple localStorage polyfill:
Demo: http://jsfiddle.net/aamir/S4X35/
HTML:
set key: foo, with value: bar<br/>
get key: foo<br/>
delete key: foo
JS:
window.store = {
localStoreSupport: function() {
try {
return 'localStorage' in window && window['localStorage'] !== null;
} catch (e) {
return false;
}
},
set: 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( this.localStoreSupport() ) {
localStorage.setItem(name, value);
}
else {
document.cookie = name+"="+value+expires+"; path=/";
}
},
get: function(name) {
if( this.localStoreSupport() ) {
var ret = localStorage.getItem(name);
//console.log(typeof ret);
switch (ret) {
case 'true':
return true;
case 'false':
return false;
default:
return ret;
}
}
else {
// cookie fallback
/*
* after adding a cookie like
* >> document.cookie = "bar=test; expires=Thu, 14 Jun 2018 13:05:38 GMT; path=/"
* the value of document.cookie may look like
* >> "foo=value; bar=test"
*/
var nameEQ = name + "="; // what we are looking for
var ca = document.cookie.split(';'); // split into separate cookies
for(var i=0;i < ca.length;i++) {
var c = ca[i]; // the current cookie
while (c.charAt(0)==' ') c = c.substring(1,c.length); // remove leading spaces
if (c.indexOf(nameEQ) == 0) { // if it is the searched cookie
var ret = c.substring(nameEQ.length,c.length);
// making "true" and "false" a boolean again.
switch (ret) {
case 'true':
return true;
case 'false':
return false;
default:
return ret;
}
}
}
return null; // no cookie found
}
},
del: function(name) {
if( this.localStoreSupport() ) {
localStorage.removeItem(name);
}
else {
this.set(name,"",-1);
}
}
}
I use PersistJS (github repository), which handles client-side storage seamlessly and transparently to your code. You use a single API and get support for the following backends:
flash: Flash 8 persistent storage.
gears: Google Gears-based persistent storage.
localstorage: HTML5 draft storage.
whatwg_db: HTML5 draft database storage.
globalstorage: HTML5 draft storage (old spec).
ie: Internet Explorer userdata behaviors.
cookie: Cookie-based persistent storage.
Any of those can be disabled—if, for example, you don't want to use cookies. With this library, you'll get native client-side storage support in IE 5.5+, Firefox 2.0+, Safari 3.1+, and Chrome; and plugin-assisted support if the browser has Flash or Gears. If you enable cookies, it will work in everything (but will be limited to 4 kB).
have you seen the polyfill page on the Modernizr wiki?
https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills
look for the webstorage section on that page and you will see 10 potential solutions (as of July 2011).
good luck!
Mark
Below is a tidied up version of Aamir Afridi's response that keeps all its code encapsulated within the local scope.
I've removed references that create a global ret variable and also removed the parsing of stored "true" and "false" strings into boolean values within the BrowserStorage.get() method, which could cause issues if one is trying to in fact store the strings "true" or "false".
Since the local storage API only supports string values, one could still store/retrieve JavaScript variable data along with their appropriate data types by encoding said data into a JSON string, which can then be decoded using a JSON encode/decode library such as https://github.com/douglascrockford/JSON-js
var BrowserStorage = (function() {
/**
* Whether the current browser supports local storage as a way of storing data
* #var {Boolean}
*/
var _hasLocalStorageSupport = (function() {
try {
return 'localStorage' in window && window['localStorage'] !== null;
} catch (e) {
return false;
}
})();
/**
* #param {String} name The name of the property to read from this document's cookies
* #return {?String} The specified cookie property's value (or null if it has not been set)
*/
var _readCookie = function(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; 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;
};
/**
* #param {String} name The name of the property to set by writing to a cookie
* #param {String} value The value to use when setting the specified property
* #param {int} [days] The number of days until the storage of this item expires
*/
var _writeCookie = function(name, value, days) {
var expiration = (function() {
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days*24*60*60*1000));
return "; expires=" + date.toGMTString();
}
else {
return "";
}
})();
document.cookie = name + "=" + value + expiration + "; path=/";
};
return {
/**
* #param {String} name The name of the property to set
* #param {String} value The value to use when setting the specified property
* #param {int} [days] The number of days until the storage of this item expires (if storage of the provided item must fallback to using cookies)
*/
set: function(name, value, days) {
_hasLocalStorageSupport
? localStorage.setItem(name, value)
: _writeCookie(name, value, days);
},
/**
* #param {String} name The name of the value to retrieve
* #return {?String} The value of the
*/
get: function(name) {
return _hasLocalStorageSupport
? localStorage.getItem(name)
: _readCookie(name);
},
/**
* #param {String} name The name of the value to delete/remove from storage
*/
remove: function(name) {
_hasLocalStorageSupport
? localStorage.removeItem(name)
: this.set(name, "", -1);
}
};
})();
I personally prefer amplify.js. It has worked really well for me in the past and I recommended it for all local storage needs.
supports IE 5+, Firefox 2+, Safari 4+, Chrome, Opera 10.5+, iPhone 2+, Android 2+ and provides a consistent API to handle storage cross-browser
store.js uses userData and IE and localStorage on other browsers.
It does not try to do anything too complex
No cookies, no flash, no jQuery needed.
Clean API.
5 kb compressed
https://github.com/marcuswestin/store.js
The MDN page for DOM storage gives several workarounds that use cookies.
Lawnchair seems to be a good alternative too
a lawnchair is sorta like a couch except smaller and outside. perfect
for html5 mobile apps that need a lightweight, adaptive, simple and
elegant persistence solution.
collections. a lawnchair instance is really just an array of objects.
adaptive persistence. the underlying store is abstracted behind a consistent interface.
pluggable collection behavior. sometimes we need collection helpers but not always.
There is realstorage, which uses Gears as a fallback.
Related
I am currently working on a some JS. It works fine in every browser apart from Microsoft Edge.
The issue is quite simple:
at the beginning of one of my scripts I declare a variable like so:
var something = localStorage.getItem('something');
Anyway the something doesn't exist yet, but the whole idea is that this can be used for reference in a later function. Firefox, Chrome, Opera and Safari don't have a problem with this but Edge does, so my question is, is the a quick fix?
Or am i going to have to rewrite my whole script because of Edge?
This is the error that edge throws by the way.
Unable to get property 'getItem' of undefined or null reference
Thanks!
Local Storage didn't work for local files in IE9, so I imagine that this is still the case in MS Edge.
I just tested it in Edge with a server on localhost and your line of code worked just fine:
> var something = localStorage.getItem('something');
> undefined
It is possible that this was a security issue in earlier versions of IE and was just never updated as the browser was developed.
Although, it appears that localStorage and sessionStorage still don't work in Edge for HTML files accessed using the 'file://' protocol.
Could you please try
var something = window.localStorage.getItem('something');
Could you also check if you have 'Enable DOM Storage' selected? You can find it under:
Internet Options -> Advanced tab -> Security group box
Also if you are running your page from local filesystem, localStorage doesn't work on IE, you have to run it from the web server.
Here is a link that provides more information of how to enable it
If someone is looking for solution older version of browser to also work to store key value for using between pages.
logic could be
function detectIE() {
var ua = window.navigator.userAgent;
var msie = ua.indexOf('MSIE ');
if (msie > 0) {
// IE 10 or older => return version number
return false;
}
var trident = ua.indexOf('Trident/');
if (trident > 0) {
// IE 11 => return version number
return false;
}
var edge = ua.indexOf('Edge/');
if (edge > 0) {
// Edge (IE 12+) => return version number
return false;
}
// other browser
return true;
}
then to set key value use something like this
if (detectIE()) { window.localStorage.setItem('key1', value1);window.localStorage.setItem('key2', value2);}else{ setCookie('key1','value1',1);var value1 = getCookie('key1');}
function setCookie(name,value,days) {
var expires = "";
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days*24*60*60*1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + (value || "") + expires + "; path=/";}
function getCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;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;}
also you can erase the cookie
function eraseCookie(name) {
document.cookie = name+'=; Max-Age=-99999999;'; }
Maybe DOMStorage is turned off? Test with this:
if (typeof window.Storage === 'undefined') {
alert('Storage turned off...');
}
I'm looking for a client-side JS library to store session variables.
I'd like a library that supports alternative storage medium, e.g. cookies when available with fallback on other techniques.
For instance, I found this one (but the last update is in 2009):
http://code.google.com/p/sessionstorage/
I'm not interested in security (apart a bit of data isolation among applications), as I'm not going to store sensitive data.
To give an example of use case, I want to display a message "Chrome user? Download the app" for chrome users, and I'd like to maintain a status in session to avoid displaying the message again to the same user. I don't want server-side sessions as I have caching enabled, so I must be able to serve the exact same page to different users.
You can use localStorage if available, and if it's not, then using cookies (or whatever you feel to):
var appToken = createToken();
try {
if (localStorage.getItem) {
localStorage.downloadAppAlert = appToken;
} else {
setCookie('downloadAppAlert', appToken, 10); // name, a string value, num. of days
}
} catch(e) {
console.log(e);
}
Then you can use some function to set your cookies - i.e. this one i just found in w3schools:
function setCookie(c_name,value,exdays)
{
var exdate=new Date();
exdate.setDate(exdate.getDate() + exdays);
var c_value=escape(value) + ((exdays==null) ? "" : "; expires="+exdate.toUTCString());
document.cookie=c_name + "=" + c_value;
}
To retrieve a cookie value by it's name - downloadAppAlert in the example - you can use the one on the w3schools link or something like this:
function readCookie(name) {
var nameEQ = name + '=';
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;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;
}
Also, to retrieve a previously setted item on the localStorage you simply:
var appToken = localStorage.getItem('downloadAppAlert');
EDIT: Sorry, with the hurries i forgot to mention what createToken() does. It is supposed to be a random alphanumeric generator function. You can find plenty on SO, like:
Random alpha-numeric string in JavaScript?
Generate random string/characters in JavaScript
Generating (pseudo)random alpha-numeric strings
Use node-client-sessions (https://github.com/mozilla/node-client-sessions) by mozilla.
I am developing an application using jQuery that uses cookies. Right now, it is located at application.html on my PC desktop.
However, I cannot store and retrieve a cookie. I had included jquery-1.7.1.min.js, json2.js, and jquery.cookie.js in my HTML file in that order.
Here is how I am storing a cookie to last for 7 days:
$.cookie("people", JSON.stringify(people_obj_array), {expires: 7});
The global array people_obj_array looks like
[
{
"name": "Adam",
"age": 1,
},
{
"name": "Bob",
"age": 2,
},
{
"name": "Cathy",
"age": 3,
},
]
When I test JSON encryption with alert(JSON.stringify(people_obj_array)), it looks fine:
However, when I retrieve this cookie via:
alert($.cookie("people"));
before even refreshing the page, an alert pops up that reads "null." Shouldn't the text be the alert JSON string? Am I using the JQuery cookies library correctly?
Just to clarify, here is how I am testing:
$.cookie("people", JSON.stringify(people_obj_array), {expires: 7}); // store
alert($.cookie("people")); // attempt to retrieve
I have Firebug, and I am willing to do some Console tests.
It's probably the fact the file is on your desktop that's causing the problem. Browsers normally behave by serving up cookies based on the domain they were received from and their path.
You may not be able to read the cookie immediately after setting it: Writing a cookie involves setting headers in a HTTP request and, likewise, reading them involves reading headers in a HTTP response.
Try hosting your page on a web-server and see if that works for you.
If you are having troubles with the cookies plugin why not just make up your own cookie functions? Read, Write and (optional) delete.
var createCookie = 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 = '';
document.cookie = name + '=' + value + expires + '; path=/';
};
var readCookie = function(name) {
var nameEQ = name + '=';
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; 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;
};
var eraseCookie = function(name) {
createCookie(name, '', -1);
};
I cannot comment on the specific plugin as I have never used it.. however these functions all work and have been tested.
So for your example:
createCookie("people", JSON.stringify(people_obj_array), 7); // store
alert(readCookie("people")); // retrieve
eraseCookie("people"); // remove
alert(readCookie("people")); // oo look i'm no longer here.
From my research jquery.cookie.js is fairly old, and doesn't seem to be maintained any longer. You might have better luck using this library instead. Its description on Google Code is "Javascript Cookie Library with jQuery bindings and JSON support", and includes methods for everything you're trying to do!
What is the shortest, accurate, and cross-browser compatible method for reading a cookie in JavaScript?
Very often, while building stand-alone scripts (where I can't have any outside dependencies), I find myself adding a function for reading cookies, and usually fall-back on the QuirksMode.org readCookie() method (280 bytes, 216 minified.)
function readCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;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;
}
It does the job, but its ugly, and adds quite a bit of bloat each time.
The method that jQuery.cookie uses something like this (modified, 165 bytes, 125 minified):
function read_cookie(key)
{
var result;
return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? (result[1]) : null;
}
Note this is not a 'Code Golf' competition: I'm legitimately interested in reducing the size of my readCookie function, and in ensuring the solution I have is valid.
Shorter, more reliable and more performant than the current best-voted answer:
const getCookieValue = (name) => (
document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)')?.pop() || ''
)
A performance comparison of various approaches is shown here:
https://jsben.ch/AhMN6
Some notes on approach:
The regex approach is not only the fastest in most browsers, it yields the shortest function as well. Additionally it should be pointed out that according to the official spec (RFC 2109), the space after the semicolon which separates cookies in the document.cookie is optional and an argument could be made that it should not be relied upon. Additionally, whitespace is allowed before and after the equals sign (=) and an argument could be made that this potential whitespace should be factored into any reliable document.cookie parser. The regex above accounts for both of the above whitespace conditions.
This will only ever hit document.cookie ONE time. Every subsequent request will be instant.
(function(){
var cookies;
function readCookie(name,c,C,i){
if(cookies){ return cookies[name]; }
c = document.cookie.split('; ');
cookies = {};
for(i=c.length-1; i>=0; i--){
C = c[i].split('=');
cookies[C[0]] = C[1];
}
return cookies[name];
}
window.readCookie = readCookie; // or expose it however you want
})();
I'm afraid there really isn't a faster way than this general logic unless you're free to use .forEach which is browser dependent (even then you're not saving that much)
Your own example slightly compressed to 120 bytes:
function read_cookie(k,r){return(r=RegExp('(^|; )'+encodeURIComponent(k)+'=([^;]*)').exec(document.cookie))?r[2]:null;}
You can get it to 110 bytes if you make it a 1-letter function name, 90 bytes if you drop the encodeURIComponent.
I've gotten it down to 73 bytes, but to be fair it's 82 bytes when named readCookie and 102 bytes when then adding encodeURIComponent:
function C(k){return(document.cookie.match('(^|; )'+k+'=([^;]*)')||0)[2]}
Assumptions
Based on the question, I believe some assumptions / requirements for this function include:
It will be used as a library function, and so meant to be dropped into any codebase;
As such, it will need to work in many different environments, i.e. work with legacy JS code, CMSes of various levels of quality, etc.;
To inter-operate with code written by other people and/or code that you do not control, the function should not make any assumptions on how cookie names or values are encoded. Calling the function with a string "foo:bar[0]" should return a cookie (literally) named "foo:bar[0]";
New cookies may be written and/or existing cookies modified at any point during lifetime of the page.
Under these assumptions, it's clear that encodeURIComponent / decodeURIComponent should not be used; doing so assumes that the code that set the cookie also encoded it using these functions.
The regular expression approach gets problematic if the cookie name can contain special characters. jQuery.cookie works around this issue by encoding the cookie name (actually both name and value) when storing a cookie, and decoding the name when retrieving a cookie. A regular expression solution is below.
Unless you're only reading cookies you control completely, it would also be advisable to read cookies from document.cookie directly and not cache the results, since there is no way to know if the cache is invalid without reading document.cookie again.
(While accessing and parsing document.cookies will be slightly slower than using a cache, it would not be as slow as reading other parts of the DOM, since cookies do not play a role in the DOM / render trees.)
Loop-based function
Here goes the Code Golf answer, based on PPK's (loop-based) function:
function readCookie(name) {
name += '=';
for (var ca = document.cookie.split(/;\s*/), i = ca.length - 1; i >= 0; i--)
if (!ca[i].indexOf(name))
return ca[i].replace(name, '');
}
which when minified, comes to 128 characters (not counting the function name):
function readCookie(n){n+='=';for(var a=document.cookie.split(/;\s*/),i=a.length-1;i>=0;i--)if(!a[i].indexOf(n))return a[i].replace(n,'');}
Regular expression-based function
Update: If you really want a regular expression solution:
function readCookie(name) {
return (name = new RegExp('(?:^|;\\s*)' + ('' + name).replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') + '=([^;]*)').exec(document.cookie)) && name[1];
}
This escapes any special characters in the cookie name before constructing the RegExp object. Minified, this comes to 134 characters (not counting the function name):
function readCookie(n){return(n=new RegExp('(?:^|;\\s*)'+(''+n).replace(/[-[\]{}()*+?.,\\^$|#\s]/g,'\\$&')+'=([^;]*)').exec(document.cookie))&&n[1];}
As Rudu and cwolves have pointed out in the comments, the regular-expression-escaping regex can be shortened by a few characters. I think it would be good to keep the escaping regex consistent (you may be using it elsewhere), but their suggestions are worth considering.
Notes
Both of these functions won't handle null or undefined, i.e. if there is a cookie named "null", readCookie(null) will return its value. If you need to handle this case, adapt the code accordingly.
code from google analytics ga.js
function c(a){
var d=[],
e=document.cookie.split(";");
a=RegExp("^\\s*"+a+"=\\s*(.*?)\\s*$");
for(var b=0;b<e.length;b++){
var f=e[b].match(a);
f&&d.push(f[1])
}
return d
}
How about this one?
function getCookie(k){var v=document.cookie.match('(^|;) ?'+k+'=([^;]*)(;|$)');return v?v[2]:null}
Counted 89 bytes without the function name.
The following function will allow differentiating between empty strings and undefined cookies. Undefined cookies will correctly return undefined and not an empty string unlike some of the other answers here.
function getCookie(name) {
return (document.cookie.match('(^|;) *'+name+'=([^;]*)')||[])[2];
}
The above worked fine for me on all browsers I checked, but as mentioned by #vanovm in comments, as per the specification the key/value may be surrounded by whitespace. Hence the following is more standard compliant.
function getCookie(name) {
return (document.cookie.match('(?:^|;)\\s*'+name.trim()+'\\s*=\\s*([^;]*?)\\s*(?:;|$)')||[])[1];
}
this in an object that you can read, write, overWrite and delete cookies.
var cookie = {
write : function (cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var expires = "expires="+d.toUTCString();
document.cookie = cname + "=" + cvalue + "; " + expires;
},
read : function (name) {
if (document.cookie.indexOf(name) > -1) {
return document.cookie.split(name)[1].split("; ")[0].substr(1)
} else {
return "";
}
},
delete : function (cname) {
var d = new Date();
d.setTime(d.getTime() - 1000);
var expires = "expires="+d.toUTCString();
document.cookie = cname + "=; " + expires;
}
};
Here goes.. Cheers!
function getCookie(n) {
let a = `; ${document.cookie}`.match(`;\\s*${n}=([^;]+)`);
return a ? a[1] : '';
}
Note that I made use of ES6's template strings to compose the regex expression.
It's 2022, everything except Internet Explorer supports the URLSearchParams API (^1) and String.prototype.replaceAll API (^2), so we can horribly (ab)use them:
const cookies = new URLSearchParams(document.cookie.replaceAll('&', '%26').replaceAll('; ', '&'));
cookies.get('cookie name'); // returns undefined if not set, string otherwise
Both of these functions look equally valid in terms of reading cookie. You can shave a few bytes off though (and it really is getting into Code Golf territory here):
function readCookie(name) {
var nameEQ = name + "=", ca = document.cookie.split(';'), i = 0, c;
for(;i < ca.length;i++) {
c = ca[i];
while (c[0]==' ') c = c.substring(1);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length);
}
return null;
}
All I did with this is collapse all the variable declarations into one var statement, removed the unnecessary second arguments in calls to substring, and replace the one charAt call into an array dereference.
This still isn't as short as the second function you provided, but even that can have a few bytes taken off:
function read_cookie(key)
{
var result;
return (result = new RegExp('(^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? result[2] : null;
}
I changed the first sub-expression in the regular expression to be a capturing sub-expression, and changed the result[1] part to result[2] to coincide with this change; also removed the unnecessary parens around result[2].
To truly remove as much bloat as possible, consider not using a wrapper function at all:
try {
var myCookie = document.cookie.match('(^|;) *myCookie=([^;]*)')[2]
} catch (_) {
// handle missing cookie
}
As long as you're familiar with RegEx, that code is reasonably clean and easy to read.
To have all cookies accessible by name in a Map:
const cookies = "a=b ; c = d ;e=";
const map = cookies.split(";").map((s) => s.split("=").map((s) => s.trim())).reduce((m, [k, v]) => (m.set(k, v), m), new Map());
console.log(map); //Map(3) {'a' => 'b', 'c' => 'd', 'e' => ''}
map.get("a"); //returns "b"
map.get("c"); //returns "d"
map.get("e"); //returns ""
(edit: posted the wrong version first.. and a non-functional one at that. Updated to current, which uses an unparam function that is much like the second example.)
Nice idea in the first example cwolves. I built on both for a fairly compact cookie reading/writing function that works across multiple subdomains. Figured I'd share in case anyone else runs across this thread looking for that.
(function(s){
s.strToObj = function (x,splitter) {
for ( var y = {},p,a = x.split (splitter),L = a.length;L;) {
p = a[ --L].split ('=');
y[p[0]] = p[1]
}
return y
};
s.rwCookie = function (n,v,e) {
var d=document,
c= s.cookies||s.strToObj(d.cookie,'; '),
h=location.hostname,
domain;
if(v){
domain = h.slice(h.lastIndexOf('.',(h.lastIndexOf('.')-1))+1);
d.cookie = n + '=' + (c[n]=v) + (e ? '; expires=' + e : '') + '; domain=.' + domain + '; path=/'
}
return c[n]||c
};
})(some_global_namespace)
If you pass rwCookie nothing, it will get
all cookies into cookie storage
Passed rwCookie a cookie name, it gets that
cookie's value from storage
Passed a cookie value, it writes the cookie and places the value in storage
Expiration defaults to session unless you specify one
Using cwolves' answer, but not using a closure nor a pre-computed hash :
// Golfed it a bit, too...
function readCookie(n){
var c = document.cookie.split('; '),
i = c.length,
C;
for(; i>0; i--){
C = c[i].split('=');
if(C[0] == n) return C[1];
}
}
...and minifying...
function readCookie(n){var c=document.cookie.split('; '),i=c.length,C;for(;i>0;i--){C=c[i].split('=');if(C[0]==n)return C[1];}}
...equals 127 bytes.
Here is the simplest solution using javascript string functions.
document.cookie.substring(document.cookie.indexOf("COOKIE_NAME"),
document.cookie.indexOf(";",
document.cookie.indexOf("COOKIE_NAME"))).
substr(COOKIE_NAME.length);
Just to throw my hat in the race, here's my proposal:
function getCookie(name) {
const cookieDict = document.cookie.split(';')
.map((x)=>x.split('='))
.reduce((accum,current) => { accum[current[0]]=current[1]; return accum;}, Object());
return cookieDict[name];
}
The above code generates a dict that stores cookies as key-value pairs (i.e., cookieDict), and afterwards accesses the property name to retrieve the cookie.
This could effectively be expressed as a one-liner, but this is only for the brave:
document.cookie.split(';').map((x)=>x.split('=')).reduce((accum,current) => { accum[current[0]]=current[1]; return accum;}, {})[name]
The absolute best approach would be to generate cookieDict at page load and then throughout the page lifecycle just access individual cookies by calling cookieDict['cookiename'].
This function doesn't work for older browser like chrome > 80.
const getCookieValue = (name) => (
document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)')?.pop() || ''
)
I solved it by using this function instead that returns undefined if the cookie is missing:
function getCookie(name) {
// Add the = sign
name = name + '=';
// Get the decoded cookie
var decodedCookie = decodeURIComponent(document.cookie);
// Get all cookies, split on ; sign
var cookies = decodedCookie.split(';');
// Loop over the cookies
for (var i = 0; i < cookies.length; i++) {
// Define the single cookie, and remove whitespace
var cookie = cookies[i].trim();
// If this cookie has the name of what we are searching
if (cookie.indexOf(name) == 0) {
// Return everything after the cookies name
return cookie.substring(name.length, cookie.length);
}
}
}
Credit: https://daily-dev-tips.com/posts/vanilla-javascript-cookies-%F0%9F%8D%AA/
You can verify if a cookie exists and it has a defined value:
function getCookie(cookiename) {
if (typeof(cookiename) == 'string' && cookiename != '') {
const COOKIES = document.cookie.split(';');
for (i = 0; i < COOKIES.length; i++) {
if (COOKIES[i].trim().startsWith(cookiename)) {
return COOKIES[i].split('=')[1];
}
}
}
return null;
}
const COOKIE_EXAMPLE = getCookie('example');
if (COOKIE_EXAMPLE == 'stackoverflow') { ... }
// If is set a cookie named "example" with value "stackoverflow"
if (COOKIE_EXAMPLE != null) { ... }
// If is set a cookie named "example" ignoring the value
It will return null if cookie doesn't exists.
Get the cookie value or undefined if it doesn't exist:
document
.cookie
.split('; ')
.filter(row => row.startsWith('cookie_name='))
.map(c=>c.split('=')[1])[0];
On chromium based browsers you can use the experimental cookieStore api:
await cookieStore.get('cookieName');
Check the Browsersupport before using!
I have set a cookie using
document.cookie =
'MYBIGCOOKIE=' + value +
'; expires=' + now.toGMTString() +
'; path=/';
Now there are between 5 and 10 cookies set on this site, is there a way to check the value ofthis cookie by name.
if (document.cookie.MYBIGCOOKIE == '1') {
alert('it is 1')
}
Use the RegExp constructor and multiple replacements to clarify the syntax:
function getCook(cookiename)
{
// Get name followed by anything except a semicolon
var cookiestring=RegExp(cookiename+"=[^;]+").exec(document.cookie);
// Return everything after the equal sign, or an empty string if the cookie name not found
return decodeURIComponent(!!cookiestring ? cookiestring.toString().replace(/^[^=]+./,"") : "");
}
//Sample usage
var cookieValue = getCook('MYBIGCOOKIE');
Unfortunately, Javascript's cookie syntax is nowhere near as nice as that. In fact, in my opinion, it's one of the worst designed parts.
When you try to read document.cookie, you get a string containing all the cookies set. You have to parse the string, separating by the semicolon ; character. Rather than writing this yourself, there are plenty of versions available on the web. My favourite is the one at quirksmode.org. This gives you createCookie, readCookie and deleteCookie functions.
function getCookie(c_name)
{
var i,x,y,ARRcookies=document.cookie.split(";");
for (i=0;i<ARRcookies.length;i++)
{
x=ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
y=ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1);
x=x.replace(/^\s+|\s+$/g,"");
if (x==c_name)
{
return unescape(y);
}
}
}
Source: W3Schools
Edit: as #zcrar70 noted, the above code is incorrect, please see the following answer Javascript getCookie functions
You can use the following function:
function getCookiesMap(cookiesString) {
return cookiesString.split(";")
.map(function(cookieString) {
return cookieString.trim().split("=");
})
.reduce(function(acc, curr) {
acc[curr[0]] = curr[1];
return acc;
}, {});
}
When, called with document.cookie as parameter, it will return an object, with the cookies keys as keys and the cookies values.
var cookies = getCookiesMap(document.cookie);
var cookieValue = cookies["MYBIGCOOKIE"];
using jquery-cookie
I find this library helpful. 3.128 kb of pure convenience.
add script
<script src="/path/to/jquery.cookie.js"></script>
set cookie
$.cookie('name', 'value');
read cookie
$.cookie('name');
One of the shortest ways is this, however as mentioned previously it can return the wrong cookie if there's similar names (MyCookie vs AnotherMyCookie):
var regex = /MyCookie=(.[^;]*)/ig;
var match = regex.exec(document.cookie);
var value = match[1];
I use this in a chrome extension so I know the name I'm setting,
and I can make sure there won't be a duplicate, more or less.
document.cookie="MYBIGCOOKIE=1";
Your cookies would look like:
"MYBIGCOOKIE=1; PHPSESSID=d76f00dvgrtea8f917f50db8c31cce9"
first of all read all cookies:
var read_cookies = document.cookie;
then split all cookies with ";":
var split_read_cookie = read_cookies.split( ";" );
then use for loop to read each value. Into loop each value split again with "=":
for ( i = 0; i < split_read_cookie.length; i++ ){
var value = split_read_cookie[i];
value = value.split( "=" );
if( value[0] == "MYBIGCOOKIE" && value[1] == "1" ){
alert( 'it is 1' );
}
}
The point of Stack Overflow is to provide a database of good quality answers, so I am going to reference some standard source code and an article that gives examples:
http://www.codelib.net/javascript/cookies.html
Note: The code is regular-expression free for greatly enhanced efficiency.
Using the source code provided, you would use cookies like this:
makeCookie('color', 'silver');
This saves a cookie indicating that the color is silver. The cookie would expire after the current session (as soon as the user quits the browser).
makeCookie('color', 'green', { domain: 'gardens.home.com' });
This saves the color green for gardens.home.com.
makeCookie('color', 'white', { domain: '.home.com', path: '/invoices' });
makeCookie('invoiceno', '0259876', { path: '/invoices', secure: true });
saves the color white for invoices viewed anywhere at home.com. The second cookie is a secure cookie, and records an invoice number. This cookie will be sent only to pages that are viewed through secure HTTPS connections, and scripts within secure pages are the only scripts allowed to access the cookie.
One HTTP host is not allowed to store or read cookies for another HTTP host. Thus, a cookie domain must be stored with at least two periods. By default, the domain is the same as the domain of the web address which created the cookie.
The path of an HTTP cookie restricts it to certain files on the HTTP host. Some browsers use a default path of /, so the cookie will be available on the whole host. Other browsers use the whole filename. In this case, if /invoices/overdue.cgi creates a cookie, only /invoices/overdue.cgi is going to get the cookie back.
When setting paths and other parameters, they are usually based on data obtained from variables like location.href, etc. These strings are already escaped, so when the cookie is created, the cookie function does not escape these values again. Only the name and value of the cookie are escaped, so we can conveniently use arbitrary names or values. Some browsers limit the total size of a cookie, or the total number of cookies which one domain is allowed to keep.
makeCookie('rememberemail', 'yes', { expires: 7 });
makeCookie('rememberlogin', 'yes', { expires: 1 });
makeCookie('allowentergrades', 'yes', { expires: 1/24 });
these cookies would remember the user's email for 7 days, the user's login for 1 day, and allow the user to enter grades without a password for 1 hour (a twenty-fourth of a day). These time limits are obeyed even if they quit the browser, and even if they don't quit the browser. Users are free to use a different browser program, or to delete cookies. If they do this, the cookies will have no effect, regardless of the expiration date.
makeCookie('rememberlogin', 'yes', { expires: -1 });
deletes the cookie. The cookie value is superfluous, and the return value false means that deletion was successful. (A expiration of -1 is used instead of 0. If we had used 0, the cookie might be undeleted until one second past the current time. In this case we would think that deletion was unsuccessful.)
Obviously, since a cookie can be deleted in this way, a new cookie will also overwrite any value of an old cookie which has the same name, including the expiration date, etc. However, cookies for completely non-overlapping paths or domains are stored separately, and the same names do not interfere with each other. But in general, any path or domain which has access to a cookie can overwrite the cookie, no matter whether or not it changes the path or domain of the new cookie.
rmCookie('rememberlogin');
also deletes the cookie, by doing makeCookie('rememberlogin', '', { expires: -1 }). This makes the cookie code longer, but saves code for people who use it, which one might think saves more code in the long run.
I use this to read cookie:
function getCookie (key) {
let value = ''
document.cookie.split(';').forEach((e)=>{
if(e.includes(key)) {
value = e.split('=')[1]
}
})
return value
}
let name = getCookie(name)
Using string.match. Returns the cookie or null
function checkForCookie(name) {
let cookieString = document.cookie.match(name + '=[^;]+')
return cookieString ? cookieString[0] : cookieString
}
Here is an example implementation, which would make this process seamless (Borrowed from AngularJs)
var CookieReader = (function(){
var lastCookies = {};
var lastCookieString = '';
function safeGetCookie() {
try {
return document.cookie || '';
} catch (e) {
return '';
}
}
function safeDecodeURIComponent(str) {
try {
return decodeURIComponent(str);
} catch (e) {
return str;
}
}
function isUndefined(value) {
return typeof value === 'undefined';
}
return function () {
var cookieArray, cookie, i, index, name;
var currentCookieString = safeGetCookie();
if (currentCookieString !== lastCookieString) {
lastCookieString = currentCookieString;
cookieArray = lastCookieString.split('; ');
lastCookies = {};
for (i = 0; i < cookieArray.length; i++) {
cookie = cookieArray[i];
index = cookie.indexOf('=');
if (index > 0) { //ignore nameless cookies
name = safeDecodeURIComponent(cookie.substring(0, index));
if (isUndefined(lastCookies[name])) {
lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));
}
}
}
}
return lastCookies;
};
})();
This is my simple solution:
function getCookieValue(userKey){
let items = document.cookie.split(";")
for(item of items){
let [key, value] = item.split("=");
if(key === userKey)
return value;
};
return null;
}
I have come up with confusing yet very simple step after 2 hrs of concentration.
suppose a cookie 'username' is stored with a value 'John Doe'.
Then call readCookies('username'), this function (defined just below ) returns the value 'John Doe'.
function readCookies(requestedKey){
var cookies = document.cookie;
var temporaryKeyIndex=-1,temporaryKeySet=false,temporaryKey,temporaryValue;
var temporaryValueIndex = -1,previousTemporaryValueIndex=-2;
var readableCookie=[];
var a;
for(var i=0;i<cookies.length;i++){
if(cookies[i]!='='&&!temporaryKeySet){
temporaryKeyIndex++;
temporaryValueIndex++;
}
else{
temporaryKeySet = true;
if(cookies[i]==';'||i==(cookies.length-1)){
temporaryKey = cookies.slice(previousTemporaryValueIndex+2,temporaryKeyIndex+1);
if(cookies.length>temporaryValueIndex+2){
temporaryValue = cookies.slice(temporaryKeyIndex+2,temporaryValueIndex+1);
}
else{
temporaryValue = cookies.slice(-((cookies.length-1) - (temporaryKeyIndex+1)))
}
alert('tempkey: '+temporaryKey+', reqKEY: '+requestedKey);
if(requestedKey.trim()==temporaryKey.trim()){
alert(1);
return temporaryValue;
}
previousTemporaryValueIndex = temporaryValueIndex;
temporaryKeyIndex = ++temporaryValueIndex;
temporaryKeySet=false;
}
else{
temporaryValueIndex++;
}
}
}
}
Here is an API which was written to smooth over the nasty browser cookie "API"
https://github.com/jaaulde/cookies
The simplest way to read a cookie I can think is using Regexp like this:
**Replace COOKIE_NAME with the name of your cookie.
document.cookie.match(/COOKIE_NAME=([^;]*);/)[1]
How does it work?
Cookies are stored in document.cookie like this: cookieName=cookieValue;cookieName2=cookieValue2;.....
The regex searches the whole cookie string for literaly "COOKIE_NAME=" and captures anything after it that is not a semicolon until it actually finds a semicolon;
Then we use [1] to get the second item from array, which is the captured group.