2
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
3
Code licensed under the BSD License:
4
http://developer.yahoo.net/yui/license.txt
8
* Utilities for cookie management
13
YUI.add("cookie", function(Y){
20
//shortcuts to functions
21
isString = L.isString,
22
isObject = L.isObject,
23
isUndefined = L.isUndefined,
24
isFunction = L.isFunction,
25
encode = encodeURIComponent,
26
decode = decodeURIComponent;
29
* Throws an error message.
31
function error(message){
32
throw new TypeError(message);
42
//-------------------------------------------------------------------------
44
//-------------------------------------------------------------------------
47
* Creates a cookie string that can be assigned into document.cookie.
48
* @param {String} name The name of the cookie.
49
* @param {String} value The value of the cookie.
50
* @param {encodeValue} encodeValue True to encode the value, false to leave as-is.
51
* @param {Object} options (Optional) Options for the cookie.
52
* @return {String} The formatted cookie string.
53
* @method _createCookieString
57
_createCookieString : function (name /*:String*/, value /*:Variant*/, encodeValue /*:Boolean*/, options /*:Object*/) /*:String*/ {
59
var text /*:String*/ = encode(name) + "=" + (encodeValue ? encode(value) : value);
62
if (isObject(options)){
64
if (options.expires instanceof Date){
65
text += "; expires=" + options.expires.toGMTString();
69
if (isString(options.path) && options.path !== ""){
70
text += "; path=" + options.path;
74
if (isString(options.domain) && options.domain !== ""){
75
text += "; domain=" + options.domain;
79
if (options.secure === true){
88
* Formats a cookie value for an object containing multiple values.
89
* @param {Object} hash An object of key-value pairs to create a string for.
90
* @return {String} A string suitable for use as a cookie value.
91
* @method _createCookieHashString
95
_createCookieHashString : function (hash /*:Object*/) /*:String*/ {
97
error("Cookie._createCookieHashString(): Argument must be an object.");
100
var text /*:Array*/ = [];
102
O.each(hash, function(value, key){
103
if (!isFunction(value) && !isUndefined(value)){
104
text.push(encode(key) + "=" + encode(String(value)));
108
return text.join("&");
112
* Parses a cookie hash string into an object.
113
* @param {String} text The cookie hash string to parse (format: n1=v1&n2=v2).
114
* @return {Object} An object containing entries for each cookie value.
115
* @method _parseCookieHash
119
_parseCookieHash : function (text /*:String*/) /*:Object*/ {
121
var hashParts /*:Array*/ = text.split("&"),
122
hashPart /*:Array*/ = NULL,
123
hash /*:Object*/ = {};
125
for (var i=0, len=hashParts.length; i < len; i++){
126
hashPart = hashParts[i].split("=");
127
hash[decode(hashPart[0])] = decode(hashPart[1]);
134
* Parses a cookie string into an object representing all accessible cookies.
135
* @param {String} text The cookie string to parse.
136
* @param {Boolean} shouldDecode (Optional) Indicates if the cookie values should be decoded or not. Default is true.
137
* @return {Object} An object containing entries for each accessible cookie.
138
* @method _parseCookieString
142
_parseCookieString : function (text /*:String*/, shouldDecode /*:Boolean*/) /*:Object*/ {
144
var cookies /*:Object*/ = {};
146
if (isString(text) && text.length > 0) {
148
var decodeValue = (shouldDecode === false ? function(s){return s;} : decode);
150
if (/[^=]+=[^=;]?(?:; [^=]+=[^=]?)?/.test(text)){
151
var cookieParts /*:Array*/ = text.split(/;\s/g),
152
cookieName /*:String*/ = NULL,
153
cookieValue /*:String*/ = NULL,
154
cookieNameValue /*:Array*/ = NULL;
156
for (var i=0, len=cookieParts.length; i < len; i++){
158
//check for normally-formatted cookie (name-value)
159
cookieNameValue = cookieParts[i].match(/([^=]+)=/i);
160
if (cookieNameValue instanceof Array){
161
cookieName = decode(cookieNameValue[1]);
162
cookieValue = decodeValue(cookieParts[i].substring(cookieNameValue[1].length+1));
164
//means the cookie does not have an "=", so treat it as a boolean flag
165
cookieName = decode(cookieParts[i]);
166
cookieValue = cookieName;
168
cookies[cookieName] = cookieValue;
176
//-------------------------------------------------------------------------
178
//-------------------------------------------------------------------------
181
* Returns the cookie value for the given name.
182
* @param {String} name The name of the cookie to retrieve.
183
* @param {Function} converter (Optional) A function to run on the value before returning
184
* it. The function is not used if the cookie doesn't exist.
185
* @return {Variant} If no converter is specified, returns a string or null if
186
* the cookie doesn't exist. If the converter is specified, returns the value
187
* returned from the converter or null if the cookie doesn't exist.
191
get : function (name /*:String*/, converter /*:Function*/) /*:Variant*/{
193
var cookies /*:Object*/ = this._parseCookieString(document.cookie);
195
if (!isString(name) || name === ""){
196
error("Cookie.get(): Cookie name must be a non-empty string.");
199
if (isUndefined(cookies[name])) {
203
if (!isFunction(converter)){
204
return cookies[name];
206
return converter(cookies[name]);
211
* Returns the value of a subcookie.
212
* @param {String} name The name of the cookie to retrieve.
213
* @param {String} subName The name of the subcookie to retrieve.
214
* @param {Function} converter (Optional) A function to run on the value before returning
215
* it. The function is not used if the cookie doesn't exist.
216
* @return {Variant} If the cookie doesn't exist, null is returned. If the subcookie
217
* doesn't exist, null if also returned. If no converter is specified and the
218
* subcookie exists, a string is returned. If a converter is specified and the
219
* subcookie exists, the value returned from the converter is returned.
223
getSub : function (name /*:String*/, subName /*:String*/, converter /*:Function*/) /*:Variant*/ {
225
var hash /*:Variant*/ = this.getSubs(name);
229
if (!isString(subName) || subName === ""){
230
error("Cookie.getSub(): Subcookie name must be a non-empty string.");
233
if (isUndefined(hash[subName])){
237
if (!isFunction(converter)){
238
return hash[subName];
240
return converter(hash[subName]);
249
* Returns an object containing name-value pairs stored in the cookie with the given name.
250
* @param {String} name The name of the cookie to retrieve.
251
* @return {Object} An object of name-value pairs if the cookie with the given name
252
* exists, null if it does not.
256
getSubs : function (name /*:String*/) /*:Object*/ {
259
if (!isString(name) || name === ""){
260
error("Cookie.getSubs(): Cookie name must be a non-empty string.");
263
var cookies = this._parseCookieString(document.cookie, false);
264
if (isString(cookies[name])){
265
return this._parseCookieHash(cookies[name]);
271
* Removes a cookie from the machine by setting its expiration date to
272
* sometime in the past.
273
* @param {String} name The name of the cookie to remove.
274
* @param {Object} options (Optional) An object containing one or more
275
* cookie options: path (a string), domain (a string),
276
* and secure (true/false). The expires option will be overwritten
278
* @return {String} The created cookie string.
282
remove : function (name /*:String*/, options /*:Object*/) /*:String*/ {
285
if (!isString(name) || name === ""){
286
error("Cookie.remove(): Cookie name must be a non-empty string.");
290
options = options || {};
291
options.expires = new Date(0);
294
return this.set(name, "", options);
298
* Removes a sub cookie with a given name.
299
* @param {String} name The name of the cookie in which the subcookie exists.
300
* @param {String} subName The name of the subcookie to remove.
301
* @param {Object} options (Optional) An object containing one or more
302
* cookie options: path (a string), domain (a string), expires (a Date object),
303
* and secure (true/false). This must be the same settings as the original
305
* @return {String} The created cookie string.
309
removeSub : function(name /*:String*/, subName /*:String*/, options /*:Object*/) /*:String*/ {
312
if (!isString(name) || name === ""){
313
error("Cookie.removeSub(): Cookie name must be a non-empty string.");
316
//check subcookie name
317
if (!isString(subName) || subName === ""){
318
error("Cookie.removeSub(): Subcookie name must be a non-empty string.");
321
//get all subcookies for this cookie
322
var subs = this.getSubs(name);
324
//delete the indicated subcookie
325
if (isObject(subs) && O.owns(subs, subName)){
326
delete subs[subName];
329
return this.setSubs(name, subs, options);
337
* Sets a cookie with a given name and value.
338
* @param {String} name The name of the cookie to set.
339
* @param {Variant} value The value to set for the cookie.
340
* @param {Object} options (Optional) An object containing one or more
341
* cookie options: path (a string), domain (a string), expires (a Date object),
342
* and secure (true/false).
343
* @return {String} The created cookie string.
347
set : function (name /*:String*/, value /*:Variant*/, options /*:Object*/) /*:String*/ {
349
if (!isString(name)){
350
error("Cookie.set(): Cookie name must be a string.");
353
if (isUndefined(value)){
354
error("Cookie.set(): Value cannot be undefined.");
358
var text /*:String*/ = this._createCookieString(name, value, true, options);
359
document.cookie = text;
364
* Sets a sub cookie with a given name to a particular value.
365
* @param {String} name The name of the cookie to set.
366
* @param {String} subName The name of the subcookie to set.
367
* @param {Variant} value The value to set.
368
* @param {Object} options (Optional) An object containing one or more
369
* cookie options: path (a string), domain (a string), expires (a Date object),
370
* and secure (true/false).
371
* @return {String} The created cookie string.
375
setSub : function (name /*:String*/, subName /*:String*/, value /*:Variant*/, options /*:Object*/) /*:String*/ {
377
if (!isString(name) || name === ""){
378
error("Cookie.setSub(): Cookie name must be a non-empty string.");
381
if (!isString(subName) || subName === ""){
382
error("Cookie.setSub(): Subcookie name must be a non-empty string.");
385
if (isUndefined(value)){
386
error("Cookie.setSub(): Subcookie value cannot be undefined.");
389
var hash /*:Object*/ = this.getSubs(name);
391
if (!isObject(hash)){
395
hash[subName] = value;
397
return this.setSubs(name, hash, options);
402
* Sets a cookie with a given name to contain a hash of name-value pairs.
403
* @param {String} name The name of the cookie to set.
404
* @param {Object} value An object containing name-value pairs.
405
* @param {Object} options (Optional) An object containing one or more
406
* cookie options: path (a string), domain (a string), expires (a Date object),
407
* and secure (true/false).
408
* @return {String} The created cookie string.
412
setSubs : function (name /*:String*/, value /*:Object*/, options /*:Object*/) /*:String*/ {
414
if (!isString(name)){
415
error("Cookie.setSubs(): Cookie name must be a string.");
418
if (!isObject(value)){
419
error("Cookie.setSubs(): Cookie value must be an object.");
422
var text /*:String*/ = this._createCookieString(name, this._createCookieHashString(value), false, options);
423
document.cookie = text;