Permalink
Browse files

initial creation of the jQuery Enhanced Cookie plugin

  • Loading branch information...
fgiasson committed Jan 5, 2012
0 parents commit 30096b62fdf4a79fda7b89d34a857dee43ad0dfe
Showing with 346 additions and 0 deletions.
  1. +102 −0 README.md
  2. +244 −0 jquery.enhanced.cookie.js
102 README.md
@@ -0,0 +1,102 @@
+Introduction
+============
+
+The enhanced version of the jQuery Cookie plugin is based on Klaus Hartl's [jQuery Cookie pluging](https://github.com/carhartl/jquery-cookie). The code of the <code>chunkedcookie</code> function comes from the original jQuery Cookie plugin.
+
+This extension to the jQuery Cookie plugin adds the capability to save content that is bigger than 4096 bytes long using two different mechanism: the usage of HTML5's localStorage, or the usage of a series of cookies where the content is chunked and saved. This extension is backward compatible with the jQuery Cookie plugin and its usage should be transparent to the users. Even if existing cookies have been created with the normal Cookie plugin, they will still be usable by this new extension. The usage syntax is the same, but 3 new options have been created.
+
+New Options
+===========
+
+Before I explains how this extension works, let me introduce three new options that have been added to the Cookie plugin. These new options will be put into context, and properly defined later in this blog post.
+
+* <code>maxChunkSize</code> - This defines the maximum number of bytes that can be saved in a single cookie. <code>(default: 3000)</code>
+* <code>maxNumberOfCookies</code> - This is the maximum number of cookies that can be created for a single domain name. <code>(default: 20)</code>
+* <code>useLocalStorage</code> - This tells the extended Cookie plugin to use the HTML5's localStorage capabilities of the browser instead of a cookie to save that value. <code>(default: true)</code>
+
+
+How Does This Extension Works?
+==============================
+
+As I said in the introduction of this blog post, this extension to the jQuery Cookie plugin does two things:
+
+* It uses the HTML5 <code>localStorage</code> capabilities of the browser if this feature is available instead of relying on the cookies. However, if cookies are needed by the developer, this feature can be turned off with the <code>useLocalStorage = false</code> option
+* If the <code>localStorage</code> option is disable, or simply not available on a browser, and if the content is bigger than the limit of the size of a cookie, then this extension will chunk the input content, and save it in multiple cookies
+
+If the <code>useLocalStorage</code> is <code>true</code>, then the plugin will try to see if the HTML5 <code>localStorage</code> mechanism is available on the browser. If it is, then it will use that local storage to save and retrieve content to the browser. If it is not, then the plugin will act like if <code>useLocalStorage</code> is <code>false</code> and the process will continue by using cookies to save and read that content from the browser.
+
+If <code>useLocalStorage is <code>false</code>, or if the HTML5 <code>localStorage</code> mechanism is not available on the browser, then the plugin will check if the content is bigger than the <code>maxChunkSize</code> option, than all the chunks will be saved in different cookies until it reaches the limit imposed by the <code>maxNumberOfCookies</code> option.
+
+If cookies are used, then two use-cases can happen:
+
+* The content is smaller than or equal to <code>maxChunkSize</code>
+* The content is bigger than <code>maxChunkSize</code>
+
+If the content is smaller than or equal to <code>maxChunkSize</code> than only one cookie will be created by the browser. The name of the cookie will be the value provided to the key parameter.
+
+If the content is bigger than <code>maxChunkSize</code> than multiple cookies will be created, one per chunk. The convention is that the name of the first cookie is the value provided to the <code>key</code> parameter. The name of the other chunks is the value provided to the <code>key</code> parameter with the chunk indicator <code>---ChunkNum</code> append to it. For example, if we have a cookie with a content of 10000 bytes that has <code>maxChunkSize</code> defined to 4000 bytes, then these three cookies would be created:
+
+* <code>cookie-name</code>
+* <code>cookie-name---1</code>
+* <code>cookie-name---2</code>
+
+Usage
+=====
+
+Create a Cookie
+---------------
+
+Let's create a cookie that expires in 365 days and where the path is the root:
+
+
+
+```javascript
+$.cookie('my-cookie', "the-content-of-my-cookie", { expires: 365, path: "/" });
+```
+
+By default, this value will be persisted in the localStorage if the browser supports it, and not in a cookie. So, let's see how to force the plugin to save the content in a cookie by using the useLocalStorage option:
+
+```javascript
+$.cookie('my-cookie', "the-content-of-my-cookie", {useLocalStorage: false, expires: 365, path: "/" });
+```
+
+Delete a Cookie
+---------------
+
+Let's see how a cookie can be deleted. The method is simply to put null as the value of the cookie. This will instruct the plugin to remove the cookie.
+
+```javascript
+$.cookie('my-cookie', null);
+```
+
+With that call, the plugin will try to remove my-cookie both in the localStorage and in the cookies.
+
+Read a Cookie
+-------------
+
+Let's see how we can read the content of a cookie:
+
+```javascript
+var value = $.cookie('my-cookie');
+```
+
+With this call, value will get the content that has been saved in the localStorage, or the cookies. This will depend if the localStorage was available in the browser.
+
+Now, let's see how to force reading the cookies by bypassing the localStorage mechanism:
+
+```javascript
+var value = $.cookie('my-cookie', {useLocalStorage: false});
+```
+
+Note that if the cookie is not existing for a <code>key</code>, then the <code>$.cookie()</code> function will return <code>null</code>.
+
+Using Limitations
+-----------------
+
+Let's see how to use the <code>maxNumberOfCookies</code> and <code>maxChunkSize</code> options to limit the size and the number of cookies to be created.
+
+With this example, the content will be saved in multiple cookies of 1000 bytes each up to 30 cookies:
+
+```javascript
+var value = $.cookie('my-cookie', "the-content-of-my-cookie-is-10000-bytes-long...", {useLocalStorage: false, maxChunkSize = 1000, maxNumberOfCookies = 30, expires: 365, path: "/" });
+```
@@ -0,0 +1,244 @@
+
+/**
+ * jQuery Extended Cookie Plugin
+ *
+ * Author: Frederick Giasson
+ *
+ * Copyright (c) 2012 Structured Dynamics LLC
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ */
+
+jQuery.cookie = function (key, value, options) {
+
+ // Check if localStorage of HTML5 exists in this browser
+ var isStorageAvailable;
+ try {
+ isStorageAvailable = window.localStorage;
+ isStorageAvailable.setItem("isStorageAvailable", "true");
+ if (isStorageAvailable.getItem("isStorageAvailable") != "true") {
+ isStorageAvailable = false;
+ }
+ } catch(e) {}
+
+ // Check if the user wants to create or delete a cookie.
+ if (arguments.length > 1 && String(value) !== "[object Object]")
+ {
+ options = jQuery.extend({}, options);
+
+ // Set the default value of the maxChunkSize option if it is not yet defined.
+ if(options.maxChunkSize == undefined)
+ {
+ options.maxChunkSize = 3000;
+ }
+
+ // Set the default value of the maxNumberOfCookies option if it is not yet defined.
+ if(options.maxNumberOfCookies == undefined)
+ {
+ options.maxNumberOfCookies = 20;
+ }
+
+ // Set the usage of the local storage to true by default
+ if(options.useLocalStorage == undefined)
+ {
+ options.useLocalStorage = true;
+ }
+
+ // Check if the user tries to delete the cookie
+ if(value === null || value === undefined)
+ {
+ // If the localStorage is available, and if the user requested its usage, then we first
+ // try to delete it from that place
+ if(options.useLocalStorage && isStorageAvailable != false)
+ {
+ localStorage.removeItem(key);
+ }
+
+ // Even if the localStora was used, we try to remove some possible old cookies
+ // Delete all possible chunks for that cookie
+ for(var i = 0; i < options.maxNumberOfCookies; i++)
+ {
+ if(i == 0)
+ {
+ // The first chunk doesn't have the chunk indicator "---"
+ var exists = $.chunkedcookie(key);
+ }
+ else
+ {
+ var exists = $.chunkedcookie(key + "---" + i);
+ }
+
+ if(exists != null)
+ {
+ $.chunkedcookie(key + "---" + i, null, options);
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ // If the localStorage is available, and if the user requested its usage,
+ // then we create that value in the localStorage of the browser (and not in a cookie)
+ if(options.useLocalStorage && isStorageAvailable != false)
+ {
+ localStorage.setItem(key, value);
+ }
+ else
+ {
+ // The user tries to create a new cookie
+
+ // Chunk the input content
+ var exp = new RegExp(".{1,"+options.maxChunkSize+"}","g");
+
+ if(value.match != undefined)
+ {
+ var chunks = value.match(exp);
+
+ // Create one cookie per chunk
+ for(var i = 0; i < chunks.length; i++)
+ {
+ if(i == 0)
+ {
+ $.chunkedcookie(key, chunks[i], options);
+ }
+ else
+ {
+ $.chunkedcookie(key + "---" + i, chunks[i], options);
+ }
+ }
+ }
+ else
+ {
+ // The value is probably a number, so we add it to a single cookie
+ $.chunkedcookie(key, value, options);
+ }
+ }
+ }
+
+ return(null);
+ }
+
+ // Check if options have been given for a cookie retreival operation
+ if(options == undefined)
+ {
+ var options;
+
+ if(arguments.length > 1 && String(value) === "[object Object]")
+ {
+ options = value;
+ }
+ else
+ {
+ options = {};
+ }
+
+ if(options.maxNumberOfCookies == undefined)
+ {
+ options.maxNumberOfCookies = 20;
+ }
+
+ if(options.useLocalStorage == undefined)
+ {
+ options.useLocalStorage = true;
+ }
+ }
+
+ // If localStorage is available, we first check if there exists a value for that name.
+ // If no value exists in the localStorage, then we continue by checking in the cookies
+ // This second checkup is needed in case that a cookie has been created in the past,
+ // using the old cookie jQuery plugin.
+ if(isStorageAvailable != false)
+ {
+ var value = localStorage.getItem(key);
+
+ if(value != undefined && value != null)
+ {
+ return(value);
+ }
+ }
+
+ var value = "";
+
+ // The user tries to get the value of a cookie
+ for(var i = 0; i < options.maxNumberOfCookies; i++)
+ {
+ // Check if the next chunk exists in the browser
+ if(i == 0)
+ {
+ var val = $.chunkedcookie(key);
+ }
+ else
+ {
+ var val = $.chunkedcookie(key + "---" + i);
+ }
+
+ // Append the value
+ if(val != null)
+ {
+ value += val;
+ }
+ else
+ {
+ // If the value is null, and we are looking at the first chunk, then
+ // it means that the cookie simply doesn't exist
+ if(i == 0)
+ {
+ return(null);
+ }
+
+ break;
+ }
+ }
+
+ // Return the entire content from all the cookies that may have been used for that value.
+ return(value);
+};
+
+/**
+ * The chunkedcookie function comes from the jQuery Cookie plugin available here:
+ *
+ * https://github.com/carhartl/jquery-cookie
+ *
+ * Copyright (c) 2010 Klaus Hartl (stilbuero.de)
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ */
+jQuery.chunkedcookie = function (key, value, options) {
+
+ // key and at least value given, set cookie...
+ if (arguments.length > 1 && String(value) !== "[object Object]") {
+ options = jQuery.extend({}, options);
+
+ if (value === null || value === undefined) {
+ options.expires = -1;
+ }
+
+ if (typeof options.expires === 'number') {
+ var days = options.expires, t = options.expires = new Date();
+ t.setDate(t.getDate() + days);
+ }
+
+ value = String(value);
+
+ return (document.cookie = [
+ encodeURIComponent(key), '=',
+ options.raw ? value : encodeURIComponent(value),
+ options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
+ options.path ? '; path=' + options.path : '',
+ options.domain ? '; domain=' + options.domain : '',
+ options.secure ? '; secure' : ''
+ ].join(''));
+ }
+
+ // key and possibly options given, get cookie...
+ options = value || {};
+ var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent;
+ return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null;
+};

0 comments on commit 30096b6

Please sign in to comment.