735

I'm trying to set a cookie depending on which CSS file I choose in my HTML. I have a form with a list of options, and different CSS files as values. When I choose a file, it should be saved to a cookie for about a week. The next time you open your HTML file, it should be the previous file you've chosen.

JavaScript code:

function cssLayout() {
    document.getElementById("css").href = this.value;
}


function setCookie(){
    var date = new Date("Februari 10, 2013");
    var dateString = date.toGMTString();
    var cookieString = "Css=document.getElementById("css").href" + dateString;
    document.cookie = cookieString;
}

function getCookie(){
    alert(document.cookie);
}

HTML code:

<form>
    Select your css layout:<br>
    <select id="myList">
        <option value="style-1.css">CSS1</option>
        <option value="style-2.css">CSS2</option>  
        <option value="style-3.css">CSS3</option>
        <option value="style-4.css">CSS4</option>
    </select>
</form>
Aaron Martin
  • 128
  • 1
  • 13
DrWooolie
  • 7,637
  • 7
  • 20
  • 19
  • 11
    `kaka = "Css=document.getElementById("css").href" + kakdatum;` is a syntax error. – Bergi Jan 28 '13 at 23:37
  • what i wonder is how to set cookie based on a choice. If i choose a specific css file, then i want that file to be saved and activated the next time i open the html file – DrWooolie Jan 28 '13 at 23:41
  • @DrWooolie How about marking an answer correct so visitors to this question will find the best answer? The top answer clearly isn't the best. – JohnAllen May 12 '14 at 20:00
  • Now (2017), some use cases make investigating the [Web Storage API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API), as opposed to cookies, worthwile. – MattBianco Aug 03 '17 at 09:02
  • A concise but fully featured modern approach to get/set cookies over at the duplicate question: https://stackoverflow.com/a/48706852/87520 – SamGoody Feb 19 '18 at 09:32
  • If you are interested in the **comparison and performance test** of many `getCookie` functions this answer could be interesting: https://stackoverflow.com/a/70118256/8573721 – Lucas Matuszewski Nov 26 '21 at 00:36

4 Answers4

1156

I find the following code to be much simpler than anything else:

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;
}
function eraseCookie(name) {   
    document.cookie = name +'=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
}

Now, calling functions

setCookie('ppkcookie','testcookie',7);

var x = getCookie('ppkcookie');
if (x) {
    [do something with x]
}

Source - http://www.quirksmode.org/js/cookies.html

They updated the page today so everything in the page should be latest as of now.

Fakhruddin Ujjainwala
  • 2,493
  • 17
  • 26
Mandeep Janjua
  • 15,583
  • 4
  • 29
  • 24
  • 3
    cookies-js has basically the same API as you've got here, with a very few extras: https://github.com/ScottHamper/Cookies – B T Aug 20 '14 at 23:45
  • 3
    Good clean and short functions. I would recommend to declare your vars at top (due to hoisting) and add curly's around your else. Unless you use Coffee script. PLus you don't need the else if you set expires as empty before your if – Mattijs Mar 04 '15 at 06:55
  • Liked the day optional function but hourly would be better to handle with lower values. Thank you so much. – m3nda Apr 10 '15 at 09:37
  • 7
    `toGMTString()` is deprecated - just FYI. [Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toGMTString) – Keith W. Nov 20 '15 at 19:48
  • 17
    This won't work if your cookie contains a semicolon. – lucaswxp Jan 11 '16 at 21:31
  • 2
    for hourly cookie, just change `days` to `hours` variable, and remove `*24` part of multiplication – Alex K Apr 07 '16 at 16:14
  • How to set a cookie with a function? – Black Apr 20 '16 at 08:41
  • 1
    @Mandeep Janjua can you update the deprecated toGMTString() method. From documentation `var str = today.toGMTString(); // deprecated! use toUTCString()` – Petroff Nov 17 '16 at 07:56
  • For noobs like me, you'll want to place the createCookie() function call below the if(x){ [do something with x} statement, or this won't work, as it always sets the cookie. – mike_freegan Mar 01 '17 at 16:58
  • You can also use createCookie function for multiple times on the same cookie to set it. – Baz Guvenkaya May 16 '17 at 07:26
  • `function setCookie( name, value = 1, days = 7 ) { document.cookie =\` name="${name}"; value=1; expires="${(new Date((new Date).getTime() + days * 86400000)).toUTCString()}"\`; }` – Nabil Kadimi Jul 14 '17 at 02:37
  • 3
    @KeithW. Does setting document.cookie to a cookie as above erase all previously set cookies for the site? – Mohammed Shareef C Aug 01 '17 at 05:03
  • 2
    @MohammedShareefC Nice question, but nice answer - https://stackoverflow.com/questions/6791944/how-exactly-does-document-cookie-work – T.Todua Dec 23 '17 at 12:19
  • 7
    Why so complex? Use `date.setDate(date.getDate() + days);` instead – dude Mar 08 '18 at 15:22
  • 1
    There this code as ES6 class https://jsfiddle.net/seyfer/zvdersna/ – Oleg Abrazhaev Sep 16 '18 at 16:03
  • 1
    The version of these functions at https://www.w3schools.com/js/js_cookies.asp seem to be much cleaner for learning. They bracket the conditions, but do not use unnecessary calls to length (in substrings). – Abandoned Cart Nov 28 '18 at 23:25
  • Why path is always "path=/"? It's better to define path as the last function argument with the default value = "/" – chill appreciator Jan 19 '19 at 12:10
  • 6
    The **eraseCookie** function didn't work for me (FireFox Developer Edition 66.0b4). Instead, I had to use the code from B T's answer: `document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/'`. – ban-geoengineering Feb 01 '19 at 20:28
  • And people responsible for the current implementation of cookie handling call themselves "developers"... – Mladen B. Feb 26 '19 at 10:54
  • 5
    Nice answer. While using semicolon(;) in cookie value I have got problem. So I refined some lines. Please update in your answer. From **function setCookie(name,value,days)** `document.cookie = name + "=" + (encodeURIComponent(value) || "") + expires + "; path=/";` From **function getCookie(name)** `if (c.indexOf(nameEQ) == 0) return decodeURIComponent(c.substring(nameEQ.length,c.length));` Use `encodeURIComponent(), decodeURIComponent()` in retutn statement; – KarthikeyanMlp Mar 01 '19 at 13:36
  • not work with \n – ssabbattini Jun 20 '19 at 06:14
  • can we also trim `ca[i]` and remove the while loop? `while (c.charAt(0)==' ') c = c.substring(1,c.length);` – Ankur Parihar Nov 23 '21 at 13:14
  • Can't we just do `document.cookie.split('; ')` (since there is no semicolon on the end)? Check this https://stackoverflow.com/a/70118256/8573721 nice comparison and **benchmark performance test** of this and other `getCookie` functions + `setCookie` function with Firefox obligatory `SameSite/Secure` & info about Google Chrome **Cookie Storage API** – Lucas Matuszewski Nov 26 '21 at 00:27
  • Thank you very much! I spent a lot of time searching the solution to my issue! You information is very useful! – Maria Dec 24 '22 at 15:11
452

These are much much better references than w3schools (the most awful web reference ever made):

Examples derived from these references:

// sets the cookie cookie1
document.cookie = 'cookie1=test; expires=Sun, 1 Jan 2023 00:00:00 UTC; path=/'

// sets the cookie cookie2 (cookie1 is *not* overwritten)
document.cookie = 'cookie2=test; expires=Sun, 1 Jan 2023 00:00:00 UTC; path=/'

// remove cookie2
document.cookie = 'cookie2=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/'

The Mozilla reference even has a nice cookie library you can use.

lin
  • 17,956
  • 4
  • 59
  • 83
B T
  • 57,525
  • 34
  • 189
  • 207
  • 31
    The expires variable is obsolete although still supported by browsers. Use max-age instead! – tyler Jul 25 '13 at 01:34
  • 64
    It looks like IE8 and below do not support `max-age`, so `expires` is the safer choice. http://blogs.msdn.com/b/ieinternals/archive/2009/08/20/wininet-ie-cookie-internals-faq.aspx – thaddeusmt Oct 08 '13 at 16:29
  • 5
    There's also a `domain` param you can set on cookies which is useful if you want to use a cookie across different sub domains on your site. – Alex W Oct 25 '13 at 20:26
  • @JoshCox Looks like that expires/max-age information came from here: http://stackoverflow.com/questions/5851727/leverage-browser-caching-expires-or-max-age-last-modified-or-etag – S. Kirby Jul 21 '14 at 10:32
  • "Expires depends on accuracy of user's clock, so it's mostly a bad choice (as most browsers support HTTP/1.1). Use max-age, to tell the browser that the file is good for that many seconds. For example, a 1 day cache would be:"... source: http://stackoverflow.com/questions/5851727/leverage-browser-caching-expires-or-max-age-last-modified-or-etag @S.Kirby thanks! – tyler Jul 23 '14 at 14:45
  • 2
    Dont work on Chrome. See here why: https://stackoverflow.com/questions/26349052/why-would-setting-document-cookie-not-work-in-chrome – Peter Apr 06 '18 at 14:10
  • 5
    Note that the MDN reference page mentions nothing about `expires` being deprecated/obsolete. That's because it can, on occasion, serve a purpose not covered by `max-age`. The value of `max-age` must be a numerical value interpreted as an amount of seconds, while the `expires` value can be set to the special value `Session` which is **not the same as `max-age=0;`**. – ocket8888 May 04 '18 at 17:57
  • 1
    Hello from 2023, the cookie finally expired – qz- Apr 01 '23 at 16:33
41

Check JavaScript Cookies on W3Schools.com for setting and getting cookie values via JS.

Just use the setCookie and getCookie methods mentioned there.

So, the code will look something like:

<script>
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;
}

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);
        }
    }
}

function cssSelected() {
    var cssSelected = $('#myList')[0].value;
    if (cssSelected !== "select") {
        setCookie("selectedCSS", cssSelected, 3);
    }
}

$(document).ready(function() {
    $('#myList')[0].value = getCookie("selectedCSS");
})
</script>
<select id="myList" onchange="cssSelected();">
    <option value="select">--Select--</option>
    <option value="style-1.css">CSS1</option>
    <option value="style-2.css">CSS2</option>
    <option value="style-3.css">CSS3</option>
    <option value="style-4.css">CSS4</option>
</select>
Stacked
  • 6,892
  • 7
  • 57
  • 73
Munish Poonia
  • 808
  • 5
  • 4
  • 14
    @BT could you elaborate on what about the above code is out of date and misinformed? – Justin Dec 10 '13 at 19:08
  • 1
    I was commenting on the w3schools website as a whole, not the particular code given in this answer – B T Dec 27 '13 at 21:23
  • 14
    @BT, I've yet to see a reference on w3schools that is out of date or contains incorrect information. – Cypher Jan 08 '14 at 01:14
  • 21
    -1 for w3schools – ohcibi Jan 13 '14 at 12:09
  • 4
    One example of w3fools being out of date is "expires", better to use "max-age" as per the comment by tman. IE8 of course, is also out of date so you might need to still use expires if you target IE8. – Chris Mountford Mar 06 '14 at 03:36
  • 11
    I just checked our analytics, and 10% of our IE users still use IE8 or lower. So using 'max-age' is a pretty bad idea. – CpnCrunch Nov 12 '14 at 19:32
  • Oh another "cool trend"... How is w3fools fools feeling about misinformation now? Ridiculous. – Fabio Milheiro Feb 07 '15 at 17:38
  • 21
    Stupidness!! +1 for the working example, I don't actually see a problem with w3schools, – amd Mar 27 '15 at 10:03
  • 2
    Escape is deprecated and will cause a lot of issues. You should change this answer. – viktor Jan 22 '18 at 15:39
36

I'm sure this question should have a more general answer with some reusable code that works with cookies as key-value pairs.

This snippet is taken from MDN and probably is trustable. This is UTF-safe object for work with cookies:

var docCookies = {
  getItem: function (sKey) {
    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;
          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 (!sKey || !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) {
    return (new RegExp("(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
  },
  keys: /* optional method: you can safely remove it! */ function () {
    var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);
    for (var nIdx = 0; nIdx < aKeys.length; nIdx++) { aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]); }
    return aKeys;
  }
};

Mozilla has some tests to prove this works in all cases.

There is an alternative snippet here:

Community
  • 1
  • 1
Dan
  • 55,715
  • 40
  • 116
  • 154
  • 6
    Just a word of warning @SandipPingle, the code provided in this answer is actually GPL licensed. – jahu Aug 09 '14 at 16:03
  • @MarcinHabuszewski thanks for pointing out. How can I use this code then(my app is not GPL licensed)? – Sandip Pingle Aug 11 '14 at 05:55
  • 8
    @SandipPingle That's the "charm" of GPL, you can't (unless you turn your app GPL). This code is somewhat similar to a generic solution to the problem, so it begs for a question: can generic code actually be licensed (or is such license valid in case of generic code)? Try using different (non-GPLed) code to solve your problem. – jahu Aug 11 '14 at 11:38
  • 19
    GPL or not, I prefer code I can **read**. – Cypher Mar 12 '15 at 00:15
  • `setItem` does not work for me. I tested it on chrome. the other methods work fine. – IgniteCoders Jun 22 '15 at 16:34
  • I set domain argument to null and works. thanks :) – IgniteCoders Jun 22 '15 at 16:43
  • oh -- and also in onsite MDN history: https://wiki.developer.mozilla.org/en-US/docs/Web/API/Document/cookie$revision/948801 was last version with it; https://wiki.developer.mozilla.org/en-US/docs/Web/API/Document/cookie$revision/948813 relocated to separate page; – Jason S Dec 10 '20 at 17:42
  • @jahu no, that may be this site's license, but the source data from MDN was added in https://wiki.developer.mozilla.org/en-US/docs/Web/API/Document/cookie$compare?to=54763&from=54762 on Jul 27 2011 and is therefore subject to public domain https://developer.mozilla.org/en-US/docs/MDN/About#Code_samples_and_snippets – Jason S Dec 10 '20 at 17:44
  • @jahu The GPL notice was added in 2013 *after* posting the body: https://wiki.developer.mozilla.org/en-US/docs/Web/API/Document/cookie$compare?to=374101&from=374099 -- the previous versions did not have a GPL notice; here's the last version w/o it: https://wiki.developer.mozilla.org/en-US/docs/Web/API/Document/cookie$revision/374099 – Jason S Dec 10 '20 at 17:48
  • @JasonS I wasn't digging through history to check if there was a different license at some point in the past. Back in the 2014, GPL was mentioned directly above the code, so I assumed that is the license. The code in question appears to have been removed from the MDN site since. Here is a link to a version from 2015 that still had the notice: https://web.archive.org/web/20150225075215/https://developer.mozilla.org/en-US/docs/Web/API/document/cookie – jahu Dec 11 '20 at 11:08