Unified · Split
| @@ -1,141 +1,172 @@ | ||
| 1 | −/*! | |
| 2 | − * Cookies.js - 0.3.1 | |
| 3 | − * Wednesday, April 24 2013 @ 2:28 AM EST | |
| 1 | +/* | |
| 2 | + * Cookies.js - 1.2.3 | |
| 3 | + * https://github.com/ScottHamper/Cookies | |
| 4 | 4 | * |
| 5 | − * Copyright (c) 2013, Scott Hamper | |
| 6 | − * Licensed under the MIT license, | |
| 7 | − * http://www.opensource.org/licenses/MIT | |
| 5 | + * This is free and unencumbered software released into the public domain. | |
| 8 | 6 | */ |
| 9 | −(function (undefined) { | |
| 7 | +(function (global, undefined) { | |
| 10 | 8 | 'use strict'; |
| 11 | 9 | |
| 12 | − var Cookies = function (key, value, options) { | |
| 13 | − return arguments.length === 1 ? | |
| 14 | − Cookies.get(key) : Cookies.set(key, value, options); | |
| 15 | − }; | |
| 10 | + var factory = function (window) { | |
| 11 | + if (typeof window.document !== 'object') { | |
| 12 | + throw new Error('Cookies.js requires a `window` with a `document` object'); | |
| 13 | + } | |
| 16 | 14 | |
| 17 | − // Allows for setter injection in unit tests | |
| 18 | − Cookies._document = document; | |
| 19 | − Cookies._navigator = navigator; | |
| 15 | + var Cookies = function (key, value, options) { | |
| 16 | + return arguments.length === 1 ? | |
| 17 | + Cookies.get(key) : Cookies.set(key, value, options); | |
| 18 | + }; | |
| 20 | 19 | |
| 21 | − Cookies.defaults = { | |
| 22 | − path: '/' | |
| 23 | − }; | |
| 20 | + // Allows for setter injection in unit tests | |
| 21 | + Cookies._document = window.document; | |
| 24 | 22 | |
| 25 | − Cookies.get = function (key) { | |
| 26 | − if (Cookies._cachedDocumentCookie !== Cookies._document.cookie) { | |
| 27 | − Cookies._renewCache(); | |
| 28 | − } | |
| 23 | + // Used to ensure cookie keys do not collide with | |
| 24 | + // built-in `Object` properties | |
| 25 | + Cookies._cacheKeyPrefix = 'cookey.'; // Hurr hurr, :) | |
| 29 | 26 | |
| 30 | − return Cookies._cache[key]; | |
| 31 | − }; | |
| 27 | + Cookies._maxExpireDate = new Date('Fri, 31 Dec 9999 23:59:59 UTC'); | |
| 32 | 28 | |
| 33 | − Cookies.set = function (key, value, options) { | |
| 34 | − options = Cookies._getExtendedOptions(options); | |
| 35 | − options.expires = Cookies._getExpiresDate(value === undefined ? -1 : options.expires); | |
| 29 | + Cookies.defaults = { | |
| 30 | + path: '/', | |
| 31 | + secure: false | |
| 32 | + }; | |
| 36 | 33 | |
| 37 | − Cookies._document.cookie = Cookies._generateCookieString(key, value, options); | |
| 34 | + Cookies.get = function (key) { | |
| 35 | + if (Cookies._cachedDocumentCookie !== Cookies._document.cookie) { | |
| 36 | + Cookies._renewCache(); | |
| 37 | + } | |
| 38 | 38 | |
| 39 | − return Cookies; | |
| 40 | − }; | |
| 39 | + var value = Cookies._cache[Cookies._cacheKeyPrefix + key]; | |
| 41 | 40 | |
| 42 | − Cookies.expire = function (key, options) { | |
| 43 | − return Cookies.set(key, undefined, options); | |
| 44 | − }; | |
| 41 | + return value === undefined ? undefined : decodeURIComponent(value); | |
| 42 | + }; | |
| 43 | + | |
| 44 | + Cookies.set = function (key, value, options) { | |
| 45 | + options = Cookies._getExtendedOptions(options); | |
| 46 | + options.expires = Cookies._getExpiresDate(value === undefined ? -1 : options.expires); | |
| 47 | + | |
| 48 | + Cookies._document.cookie = Cookies._generateCookieString(key, value, options); | |
| 45 | 49 | |
| 46 | − Cookies._getExtendedOptions = function (options) { | |
| 47 | − return { | |
| 48 | − path: options && options.path || Cookies.defaults.path, | |
| 49 | − domain: options && options.domain || Cookies.defaults.domain, | |
| 50 | − expires: options && options.expires || Cookies.defaults.expires, | |
| 51 | − secure: options && options.secure !== undefined ? options.secure : Cookies.defaults.secure | |
| 50 | + return Cookies; | |
| 52 | 51 | }; |
| 53 | − }; | |
| 54 | 52 | |
| 55 | − Cookies._isValidDate = function (date) { | |
| 56 | − return Object.prototype.toString.call(date) === '[object Date]' && !isNaN(date.getTime()); | |
| 57 | − }; | |
| 53 | + Cookies.expire = function (key, options) { | |
| 54 | + return Cookies.set(key, undefined, options); | |
| 55 | + }; | |
| 58 | 56 | |
| 59 | − Cookies._getExpiresDate = function (expires, now) { | |
| 60 | − now = now || new Date(); | |
| 61 | − switch (typeof expires) { | |
| 62 | − case 'number': expires = new Date(now.getTime() + expires * 1000); break; | |
| 63 | − case 'string': expires = new Date(expires); break; | |
| 64 | − } | |
| 57 | + Cookies._getExtendedOptions = function (options) { | |
| 58 | + return { | |
| 59 | + path: options && options.path || Cookies.defaults.path, | |
| 60 | + domain: options && options.domain || Cookies.defaults.domain, | |
| 61 | + expires: options && options.expires || Cookies.defaults.expires, | |
| 62 | + secure: options && options.secure !== undefined ? options.secure : Cookies.defaults.secure | |
| 63 | + }; | |
| 64 | + }; | |
| 65 | 65 | |
| 66 | − if (expires && !Cookies._isValidDate(expires)) { | |
| 67 | − throw new Error('`expires` parameter cannot be converted to a valid Date instance'); | |
| 68 | − } | |
| 66 | + Cookies._isValidDate = function (date) { | |
| 67 | + return Object.prototype.toString.call(date) === '[object Date]' && !isNaN(date.getTime()); | |
| 68 | + }; | |
| 69 | 69 | |
| 70 | − return expires; | |
| 71 | − }; | |
| 70 | + Cookies._getExpiresDate = function (expires, now) { | |
| 71 | + now = now || new Date(); | |
| 72 | 72 | |
| 73 | − Cookies._generateCookieString = function (key, value, options) { | |
| 74 | − key = encodeURIComponent(key); | |
| 75 | − value = (value + '').replace(/[^!#$&-+\--:<-\[\]-~]/g, encodeURIComponent); | |
| 76 | − options = options || {}; | |
| 73 | + if (typeof expires === 'number') { | |
| 74 | + expires = expires === Infinity ? | |
| 75 | + Cookies._maxExpireDate : new Date(now.getTime() + expires * 1000); | |
| 76 | + } else if (typeof expires === 'string') { | |
| 77 | + expires = new Date(expires); | |
| 78 | + } | |
| 77 | 79 | |
| 78 | − var cookieString = key + '=' + value; | |
| 79 | − cookieString += options.path ? ';path=' + options.path : ''; | |
| 80 | − cookieString += options.domain ? ';domain=' + options.domain : ''; | |
| 81 | − cookieString += options.expires ? ';expires=' + options.expires.toGMTString() : ''; | |
| 82 | − cookieString += options.secure ? ';secure' : ''; | |
| 80 | + if (expires && !Cookies._isValidDate(expires)) { | |
| 81 | + throw new Error('`expires` parameter cannot be converted to a valid Date instance'); | |
| 82 | + } | |
| 83 | 83 | |
| 84 | − return cookieString; | |
| 85 | − }; | |
| 84 | + return expires; | |
| 85 | + }; | |
| 86 | 86 | |
| 87 | − Cookies._getCookieObjectFromString = function (documentCookie) { | |
| 88 | − var cookieObject = {}; | |
| 89 | − var cookiesArray = documentCookie ? documentCookie.split('; ') : []; | |
| 87 | + Cookies._generateCookieString = function (key, value, options) { | |
| 88 | + key = key.replace(/[^#$&+\^`|]/g, encodeURIComponent); | |
| 89 | + key = key.replace(/\(/g, '%28').replace(/\)/g, '%29'); | |
| 90 | + value = (value + '').replace(/[^!#$&-+\--:<-\[\]-~]/g, encodeURIComponent); | |
| 91 | + options = options || {}; | |
| 90 | 92 | |
| 91 | − for (var i = 0; i < cookiesArray.length; i++) { | |
| 92 | − var cookieKvp = Cookies._getKeyValuePairFromCookieString(cookiesArray[i]); | |
| 93 | + var cookieString = key + '=' + value; | |
| 94 | + cookieString += options.path ? ';path=' + options.path : ''; | |
| 95 | + cookieString += options.domain ? ';domain=' + options.domain : ''; | |
| 96 | + cookieString += options.expires ? ';expires=' + options.expires.toUTCString() : ''; | |
| 97 | + cookieString += options.secure ? ';secure' : ''; | |
| 93 | 98 | |
| 94 | − if (cookieObject[cookieKvp.key] === undefined) { | |
| 95 | − cookieObject[cookieKvp.key] = cookieKvp.value; | |
| 99 | + return cookieString; | |
| 100 | + }; | |
| 101 | + | |
| 102 | + Cookies._getCacheFromString = function (documentCookie) { | |
| 103 | + var cookieCache = {}; | |
| 104 | + var cookiesArray = documentCookie ? documentCookie.split('; ') : []; | |
| 105 | + | |
| 106 | + for (var i = 0; i < cookiesArray.length; i++) { | |
| 107 | + var cookieKvp = Cookies._getKeyValuePairFromCookieString(cookiesArray[i]); | |
| 108 | + | |
| 109 | + if (cookieCache[Cookies._cacheKeyPrefix + cookieKvp.key] === undefined) { | |
| 110 | + cookieCache[Cookies._cacheKeyPrefix + cookieKvp.key] = cookieKvp.value; | |
| 111 | + } | |
| 96 | 112 | } |
| 97 | − } | |
| 98 | 113 | |
| 99 | − return cookieObject; | |
| 100 | − }; | |
| 114 | + return cookieCache; | |
| 115 | + }; | |
| 101 | 116 | |
| 102 | − Cookies._getKeyValuePairFromCookieString = function (cookieString) { | |
| 103 | − // "=" is a valid character in a cookie value according to RFC6265, so cannot `split('=')` | |
| 104 | − var separatorIndex = cookieString.indexOf('='); | |
| 117 | + Cookies._getKeyValuePairFromCookieString = function (cookieString) { | |
| 118 | + // "=" is a valid character in a cookie value according to RFC6265, so cannot `split('=')` | |
| 119 | + var separatorIndex = cookieString.indexOf('='); | |
| 120 | + | |
| 121 | + // IE omits the "=" when the cookie value is an empty string | |
| 122 | + separatorIndex = separatorIndex < 0 ? cookieString.length : separatorIndex; | |
| 123 | + | |
| 124 | + var key = cookieString.substr(0, separatorIndex); | |
| 125 | + var decodedKey; | |
| 126 | + try { | |
| 127 | + decodedKey = decodeURIComponent(key); | |
| 128 | + } catch (e) { | |
| 129 | + if (console && typeof console.error === 'function') { | |
| 130 | + console.error('Could not decode cookie with key "' + key + '"', e); | |
| 131 | + } | |
| 132 | + } | |
| 105 | 133 | |
| 106 | − // IE omits the "=" when the cookie value is an empty string | |
| 107 | − separatorIndex = separatorIndex < 0 ? cookieString.length : separatorIndex; | |
| 134 | + return { | |
| 135 | + key: decodedKey, | |
| 136 | + value: cookieString.substr(separatorIndex + 1) // Defer decoding value until accessed | |
| 137 | + }; | |
| 138 | + }; | |
| 108 | 139 | |
| 109 | − return { | |
| 110 | − key: decodeURIComponent(cookieString.substr(0, separatorIndex)), | |
| 111 | − value: decodeURIComponent(cookieString.substr(separatorIndex + 1)) | |
| 140 | + Cookies._renewCache = function () { | |
| 141 | + Cookies._cache = Cookies._getCacheFromString(Cookies._document.cookie); | |
| 142 | + Cookies._cachedDocumentCookie = Cookies._document.cookie; | |
| 112 | 143 | }; |
| 113 | − }; | |
| 114 | 144 | |
| 115 | − Cookies._renewCache = function () { | |
| 116 | − Cookies._cache = Cookies._getCookieObjectFromString(Cookies._document.cookie); | |
| 117 | − Cookies._cachedDocumentCookie = Cookies._document.cookie; | |
| 118 | − }; | |
| 145 | + Cookies._areEnabled = function () { | |
| 146 | + var testKey = 'cookies.js'; | |
| 147 | + var areEnabled = Cookies.set(testKey, 1).get(testKey) === '1'; | |
| 148 | + Cookies.expire(testKey); | |
| 149 | + return areEnabled; | |
| 150 | + }; | |
| 119 | 151 | |
| 120 | − Cookies._areEnabled = function () { | |
| 121 | − return Cookies._navigator.cookieEnabled || | |
| 122 | − Cookies.set('cookies.js', 1).get('cookies.js') === '1'; | |
| 123 | − }; | |
| 152 | + Cookies.enabled = Cookies._areEnabled(); | |
| 124 | 153 | |
| 125 | − Cookies.enabled = Cookies._areEnabled(); | |
| 154 | + return Cookies; | |
| 155 | + }; | |
| 156 | + var cookiesExport = (global && typeof global.document === 'object') ? factory(global) : factory; | |
| 126 | 157 | |
| 127 | 158 | // AMD support |
| 128 | 159 | if (typeof define === 'function' && define.amd) { |
| 129 | − define(function () { return Cookies; }); | |
| 130 | − // CommonJS and Node.js module support. | |
| 131 | − } else if (typeof exports !== 'undefined') { | |
| 160 | + define(function () { return cookiesExport; }); | |
| 161 | + // CommonJS/Node.js support | |
| 162 | + } else if (typeof exports === 'object') { | |
| 132 | 163 | // Support Node.js specific `module.exports` (which can be a function) |
| 133 | − if (typeof module !== 'undefined' && module.exports) { | |
| 134 | − exports = module.exports = Cookies; | |
| 164 | + if (typeof module === 'object' && typeof module.exports === 'object') { | |
| 165 | + exports = module.exports = cookiesExport; | |
| 135 | 166 | } |
| 136 | 167 | // But always support CommonJS module 1.1.1 spec (`exports` cannot be a function) |
| 137 | − exports.Cookies = Cookies; | |
| 168 | + exports.Cookies = cookiesExport; | |
| 138 | 169 | } else { |
| 139 | − window.Cookies = Cookies; | |
| 170 | + global.Cookies = cookiesExport; | |
| 140 | 171 | } |
| 141 | −})(); | |
| 172 | +})(typeof window === 'undefined' ? this : window); | |