A little framework: a complete cookies reader/writer with full Unicode support
As cookies are just specially formatted strings it is sometimes difficult to manage them. The following library aims to abstract the access to document.cookie by defining an object (docCookies) that is partially consistent with a Storage object. It also offers full Unicode support.
The following code is also available on GitHub.
Library
/*\
|*|
|*| :: cookies.js ::
|*|
|*| A complete cookies reader/writer framework with full unicode support.
|*|
|*| Revision #3 - July 13th, 2017
|*|
|*| https://developer.mozilla.org/en-US/docs/Web/API/document.cookie
|*| https://developer.mozilla.org/User:fusionchess
|*| https://github.com/madmurphy/cookies.js
|*|
|*| This framework is released under the GNU Public License, version 3 or later.
|*| http://www.gnu.org/licenses/gpl-3.0-standalone.html
|*|
|*| Syntaxes:
|*|
|*| * docCookies.setItem(name, value[, end[, path[, domain[, secure]]]])
|*| * docCookies.getItem(name)
|*| * docCookies.removeItem(name[, path[, domain]])
|*| * docCookies.hasItem(name)
|*| * docCookies.keys()
|*|
\*/
var docCookies = {
getItem: function (sKey) {
if (!sKey) { return null; }
return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
},
setItem: function (sKey, sValue, vEnd, sPath, sDomain, bSecure) {
if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; }
var sExpires = "";
if (vEnd) {
switch (vEnd.constructor) {
case Number:
sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
/*
Note: Despite officially defined in RFC 6265, the use of `max-age` is not compatible with any
version of Internet Explorer, Edge and some mobile browsers. Therefore passing a number to
the end parameter might not work as expected. A possible solution might be to convert the the
relative time to an absolute time. For instance, replacing the previous line with:
*/
/*
sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; expires=" + (new Date(vEnd * 1e3 + Date.now())).toUTCString();
*/
break;
case String:
sExpires = "; expires=" + vEnd;
break;
case Date:
sExpires = "; expires=" + vEnd.toUTCString();
break;
}
}
document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");
return true;
},
removeItem: function (sKey, sPath, sDomain) {
if (!this.hasItem(sKey)) { return false; }
document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "");
return true;
},
hasItem: function (sKey) {
if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; }
return (new RegExp("(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
},
keys: function () {
var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);
for (var nLen = aKeys.length, nIdx = 0; nIdx < nLen; nIdx++) { aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]); }
return aKeys;
}
};
Fri, 31 Dec 9999 23:59:59 GMT. If, for any reason, you are afraid of such a date, use the conventional date of the end of the world Tue, 19 Jan 2038 03:14:07 GMT – which is the maximum number of seconds elapsed since 1 January 1970 00:00:00 UTC expressible by a signed 32-bit integer (i.e., 01111111111111111111111111111111 which is new Date(0x7fffffff * 1e3)).Writing a cookie
Syntax
docCookies.setItem(name, value[, end[, path[, domain[, secure]]]])
Description
Create/overwrite a cookie.
Parameters
name- The name of the cookie to create/overwrite (
string). value- The value of the cookie (
string). endOptional- The
max-agein seconds (e.g.31536e3for a year,Infinityfor a never-expire cookie), or theexpiresdate inGMTStringformat or asDateobject; if not, the specified the cookie will expire at the end of the session (number– finite orInfinity–string,Dateobject ornull).Note: Despite officially defined in RFC 6265, the use of
max-ageis not compatible with any version of Internet Explorer, Edge and some mobile browsers. Therefore passing a number to theendparameter might not work as expected. A possible solution might be to convert the the relative time to an absolute time. For instance, the following code:docCookies.setItem("mycookie", "Hello world!", 150);can be rewritten using an absolute date, as in the following example:
function maxAgeToGMT (nMaxAge) { return nMaxAge === Infinity ? "Fri, 31 Dec 9999 23:59:59 GMT" : (new Date(nMaxAge * 1e3 + Date.now())).toUTCString(); } docCookies.setItem("mycookie", "Hello world!", maxAgeToGMT(150));In the code above the function
maxAgeToGMT()is used to create aGMTStringfrom a relative time (i.e., from an "age"). pathOptional- The
pathfrom where the cookie will be readable. E.g.,"/","/mydir"; if not specified, defaults to the current path of the current document location (stringornull). The path must be absolute (see RFC 2965). For more information on how to use relative paths in this argument, see this paragraph. domainOptional- The
domainfrom where the cookie will be readable. E.g.,"example.com",".example.com"(includes all subdomains) or"subdomain.example.com"; if not specified, defaults to the host portion of the current document location (stringornull). secureOptional- The cookie will be transmitted only over
secureprotocol as https (booleanornull).
Getting a cookie
Syntax
docCookies.getItem(name)
Description
Read a cookie. If the cookie doesn't exist a null value will be returned.
Parameters
Removing a cookie
Syntax
docCookies.removeItem(name[, path[, domain]])
Description
Delete a cookie.
Parameters
name- The name of the cookie to remove (
string). pathOptional- E.g.,
"/","/mydir"; if not specified, defaults to the current path of the current document location (stringornull). The path must be absolute (see RFC 2965). For more information on how to use relative paths in this argument, see this paragraph. domainOptional- E.g.,
"example.com", or"subdomain.example.com"; if not specified, defaults to the host portion of the current document location (stringornull), but not including subdomains. Contrary to earlier specifications, leading dots in domain names are ignored. If a domain is specified, subdomains are always included.Note: To delete cookies that span over subdomains, you need to explicitate the domain attribute inremoveItem()as well assetItem().
Testing a cookie
Syntax
docCookies.hasItem(name)
Description
Check whether a cookie exists in the current position.
Parameters
Getting the list of all cookies
Syntax
docCookies.keys()
Description
Returns an array of all readable cookies from this location.
Example usage:
docCookies.setItem("test0", "Hello world!");
docCookies.setItem("test1", "Unicode test: \u00E0\u00E8\u00EC\u00F2\u00F9", Infinity);
docCookies.setItem("test2", "Hello world!", new Date(2020, 5, 12));
docCookies.setItem("test3", "Hello world!", new Date(2027, 2, 3), "/blog");
docCookies.setItem("test4", "Hello world!", "Wed, 19 Feb 2127 01:04:55 GMT");
docCookies.setItem("test5", "Hello world!", "Fri, 20 Aug 88354 14:07:15 GMT", "/home");
docCookies.setItem("test6", "Hello world!", 150);
docCookies.setItem("test7", "Hello world!", 245, "/content");
docCookies.setItem("test8", "Hello world!", null, null, "example.com");
docCookies.setItem("test9", "Hello world!", null, null, null, true);
docCookies.setItem("test1;=", "Safe character test;=", Infinity);
alert(docCookies.keys().join("\n"));
alert(docCookies.getItem("test1"));
alert(docCookies.getItem("test5"));
docCookies.removeItem("test1");
docCookies.removeItem("test5", "/home");
alert(docCookies.getItem("test1"));
alert(docCookies.getItem("test5"));
alert(docCookies.getItem("unexistingCookie"));
alert(docCookies.getItem());
alert(docCookies.getItem("test1;="));