From 9f2b6240f602f989070562dff5ca01ba73cc77d4 Mon Sep 17 00:00:00 2001 From: John Bintz Date: Fri, 25 Nov 2011 10:20:13 -0500 Subject: [PATCH] better cookie library --- README.md | 2 +- Rakefile | 6 +- vendor/assets/javascripts/jquery.cookie.js | 41 -- vendor/assets/javascripts/jquery.cookies.js | 706 ++++++++++++++++++++ 4 files changed, 711 insertions(+), 44 deletions(-) delete mode 100644 vendor/assets/javascripts/jquery.cookie.js create mode 100644 vendor/assets/javascripts/jquery.cookies.js diff --git a/README.md b/README.md index 2ca5b42..61a66ec 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Everything that I use JavaScript-wise goes in here, so I can pull it in to all m Every other project is owned by the original owner, I'm just aggregating for my own convenience. -* [jquery.cookie.js](https://github.com/carhartl/jquery-cookie) +* [jquery.cookies.js](http://code.google.com/p/cookies) * [jquery.elastic.js](http://unwrongest.com/projects/elastic/) * [jquery.viewport.js](https://github.com/borbit/jquery.viewport) * [Better-Autocomplete](https://github.com/betamos/Better-Autocomplete) diff --git a/Rakefile b/Rakefile index 80e1467..dfcb2f7 100644 --- a/Rakefile +++ b/Rakefile @@ -12,8 +12,8 @@ def process_zip_url(url, &block) end sources = { - 'jquery.cookie' => [ - 'https://raw.github.com/carhartl/jquery-cookie/master/jquery.cookie.js' + 'jquery.cookies' => [ + 'http://cookies.googlecode.com/svn/trunk/jquery.cookies.js' ], 'jquery-elastic' => lambda { process_zip_url('http://jquery-elastic.googlecode.com/files/jquery.elastic-1.6.11.zip') do |entry| @@ -46,6 +46,8 @@ sources = { desc 'Update verything' task :update do + rm_rf 'vendor/assets' + sources.each do |name, files| case files when Array diff --git a/vendor/assets/javascripts/jquery.cookie.js b/vendor/assets/javascripts/jquery.cookie.js deleted file mode 100644 index 6a3e394..0000000 --- a/vendor/assets/javascripts/jquery.cookie.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * jQuery Cookie plugin - * - * 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.cookie = 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; -}; diff --git a/vendor/assets/javascripts/jquery.cookies.js b/vendor/assets/javascripts/jquery.cookies.js new file mode 100644 index 0000000..ff6412b --- /dev/null +++ b/vendor/assets/javascripts/jquery.cookies.js @@ -0,0 +1,706 @@ +/** + * Copyright (c) 2005 - 2011, James Auldridge + * All rights reserved. + * + * Licensed under the BSD, MIT, and GPL (your choice!) Licenses: + * @link http://code.google.com/p/cookies/wiki/License + * + * Last eror free JSHint: 20110418 12:14 + * @link http://jshint.com/ + * Checked Options: + * Disallow bitwise operators + * Require curly braces around all blocks + * Require === + * Require for..in statements to be filtered + * Require variables to be declared before usage + * Environment + * Browser + * jQuery + */ +( function( global ) +{ + "use strict"; + + var document, Object, jaaulde; + + /* + * localize global variables which are used more than once + */ + document = global.document; + Object = global.Object; + + /* + * jaaulde Namespace preparation - the only var introduced into global space + */ + jaaulde = global.jaaulde = ( global.jaaulde || {} ); + jaaulde.utils = jaaulde.utils || {}; + + jaaulde.utils.cookies = ( function() + { + /* Private vars */ + var defaultOptions, + /* Private functions */ + resolveOptions, assembleOptionsString, isNaN, trim, parseCookies, Constructor; + + defaultOptions = { + expiresAt: null, + path: '/', + domain: null, + secure: false + }; + + /** + * resolveOptions - receive an options object and ensure all options are present and valid, replacing with defaults where necessary + * would prefer jQuery.extend here, but we want this library to work without jQuery + * @access private + * @static + * @parameter Object options - optional options to start with + * @return Object complete and valid options object + */ + resolveOptions = function( options ) + { + var returnValue, expireDate; + + if( typeof options !== 'object' || options === null ) + { + returnValue = defaultOptions; + } + else + { + returnValue = { + expiresAt: defaultOptions.expiresAt, + path: defaultOptions.path, + domain: defaultOptions.domain, + secure: defaultOptions.secure + }; + + if( typeof options.expiresAt === 'object' && options.expiresAt instanceof Date ) + { + returnValue.expiresAt = options.expiresAt; + } + else if( typeof options.hoursToLive === 'number' && options.hoursToLive !== 0 ) + { + expireDate = new global.Date(); + expireDate.setTime( expireDate.getTime() + ( options.hoursToLive * 60 * 60 * 1000 ) ); + returnValue.expiresAt = expireDate; + } + + if( typeof options.path === 'string' && options.path !== '' ) + { + returnValue.path = options.path; + } + + if( typeof options.domain === 'string' && options.domain !== '' ) + { + returnValue.domain = options.domain; + } + + if( options.secure === true ) + { + returnValue.secure = options.secure; + } + } + + return returnValue; + }; + /** + * assembleOptionsString - analyze options and assemble appropriate string for setting a cookie with those options + * + * @access private + * @static + * @parameter options OBJECT - optional options to start with + * @return STRING - complete and valid cookie setting options + */ + assembleOptionsString = function( options ) + { + options = resolveOptions( options ); + + return ( + ( typeof options.expiresAt === 'object' && options.expiresAt instanceof Date ? '; expires=' + options.expiresAt.toGMTString() : '' ) + + '; path=' + options.path + + ( typeof options.domain === 'string' ? '; domain=' + options.domain : '' ) + + ( options.secure === true ? '; secure' : '' ) + ); + }; + /** + * trim - remove left and right whitespace + * Some logic borrowed from http://jquery.com/ + * + * @access private + * @static + * @parameter data STRING + * @return STRING + */ + trim = global.String.prototype.trim ? + function( data ) + { + return global.String.prototype.trim.call( data ); + } : + ( function() + { + var trimLeft, trimRight; + + trimLeft = /^\s+/; + trimRight = /\s+$/; + + return function( data ) + { + return data.replace( trimLeft, '' ).replace( trimRight, '' ); + }; + }() ); + /** + * isNaN - check if given value is not a number + * Borrowed from http://jquery.com/ + * + * @access private + * @static + * @parameter obj MIXED + * @return BOOL + */ + isNaN = ( function() + { + var rdigit = /\d/, isNaN = global.isNaN; + return function( obj ) + { + return ( obj === null || ! rdigit.test( obj ) || isNaN( obj ) ); + }; + }() ); + /** + * parseCookies - retrieve document.cookie string and break it into a hash with values decoded and unserialized + * + * @access private + * @static + * @return OBJECT - hash of cookies from document.cookie + */ + parseCookies = ( function() + { + var parseJSON, rbrace; + + parseJSON = global.JSON && global.JSON.parse ? + ( function() + { + var rvalidchars, rvalidescape, rvalidtokens, rvalidbraces; + + rvalidchars = /^[\],:{}\s]*$/; + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g; + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g; + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g; + + return function( data ) + { + var returnValue, validJSON; + + returnValue = null; + + if( typeof data === 'string' && data !== '' ) + { + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = trim( data ); + + if( data !== '' ) + { + try + { + // Make sure the incoming data is actual JSON. Logic borrowed from http://json.org/json2.js + validJSON = rvalidchars.test( data.replace( rvalidescape, '@' ).replace( rvalidtokens, ']' ).replace( rvalidbraces, '' ) ); + + returnValue = validJSON ? + global.JSON.parse( data ) : + null; + } + catch( e1 ) + { + returnValue = null; + } + } + } + + return returnValue; + }; + }() ) : + function() + { + return null; + }; + + rbrace = /^(?:\{.*\}|\[.*\])$/; + + return function() + { + var cookies, splitOnSemiColons, cookieCount, i, splitOnEquals, name, rawValue, value; + + cookies = {}; + splitOnSemiColons = document.cookie.split( ';' ); + cookieCount = splitOnSemiColons.length; + + for( i = 0; i < cookieCount; i = i + 1 ) + { + splitOnEquals = splitOnSemiColons[i].split( '=' ); + + name = trim( splitOnEquals.shift() ); + if( splitOnEquals.length >= 1 ) + { + rawValue = splitOnEquals.join( '=' ); + } + else + { + rawValue = ''; + } + + try + { + value = decodeURIComponent( rawValue ); + } + catch( e2 ) + { + value = rawValue; + } + + //Logic borrowed from http://jquery.com/ dataAttr method + try + { + value = value === 'true' ? + true : + value === 'false' ? + false : + ! isNaN( value ) ? + parseFloat( value ) : + rbrace.test( value ) ? + parseJSON( value ) : + value; + } + catch( e3 ) {} + + cookies[name] = value; + } + return cookies; + }; + }() ); + + Constructor = function(){}; + + /** + * get - get one, several, or all cookies + * + * @access public + * @paramater Mixed cookieName - String:name of single cookie; Array:list of multiple cookie names; Void (no param):if you want all cookies + * @return Mixed - Value of cookie as set; Null:if only one cookie is requested and is not found; Object:hash of multiple or all cookies (if multiple or all requested); + */ + Constructor.prototype.get = function( cookieName ) + { + var returnValue, item, cookies; + + cookies = parseCookies(); + + if( typeof cookieName === 'string' ) + { + returnValue = ( typeof cookies[cookieName] !== 'undefined' ) ? cookies[cookieName] : null; + } + else if( typeof cookieName === 'object' && cookieName !== null ) + { + returnValue = {}; + for( item in cookieName ) + { + if( Object.prototype.hasOwnProperty.call( cookieName, item ) ) + { + if( typeof cookies[cookieName[item]] !== 'undefined' ) + { + returnValue[cookieName[item]] = cookies[cookieName[item]]; + } + else + { + returnValue[cookieName[item]] = null; + } + } + } + } + else + { + returnValue = cookies; + } + + return returnValue; + }; + /** + * filter - get array of cookies whose names match the provided RegExp + * + * @access public + * @paramater Object RegExp - The regular expression to match against cookie names + * @return Mixed - Object:hash of cookies whose names match the RegExp + */ + Constructor.prototype.filter = function( cookieNameRegExp ) + { + var cookieName, returnValue, cookies; + + returnValue = {}; + cookies = parseCookies(); + + if( typeof cookieNameRegExp === 'string' ) + { + cookieNameRegExp = new RegExp( cookieNameRegExp ); + } + + for( cookieName in cookies ) + { + if( Object.prototype.hasOwnProperty.call( cookies, cookieName ) && cookieName.match( cookieNameRegExp ) ) + { + returnValue[cookieName] = cookies[cookieName]; + } + } + + return returnValue; + }; + /** + * set - set or delete a cookie with desired options + * + * @access public + * @paramater String cookieName - name of cookie to set + * @paramater Mixed value - Any JS value. If not a string, will be JSON encoded (http://code.google.com/p/cookies/wiki/JSON); NULL to delete + * @paramater Object options - optional list of cookie options to specify + * @return void + */ + Constructor.prototype.set = function( cookieName, value, options ) + { + if( typeof options !== 'object' || options === null ) + { + options = {}; + } + + // TODO: consider value serialization method to parallel parse cookies + if( typeof value === 'undefined' || value === null ) + { + value = ''; + options.hoursToLive = -8760; + } + else + { + //Logic borrowed from http://jquery.com/ dataAttr method and reversed + value = value === true ? + 'true' : + value === false ? + 'false' : + ! isNaN( value ) ? + '' + value : + value; + if( typeof value !== 'string' ) + { + if( typeof JSON === 'object' && JSON !== null && typeof JSON.stringify === 'function' ) + { + value = JSON.stringify( value ); + } + else + { + throw new Error( 'cookies.set() received value which could not be serialized.' ); + } + } + } + + var optionsString = assembleOptionsString( options ); + + document.cookie = cookieName + '=' + encodeURIComponent( value ) + optionsString; + }; + /** + * del - delete a cookie (domain and path options must match those with which the cookie was set; this is really an alias for set() with parameters simplified for this use) + * + * @access public + * @paramater MIxed cookieName - String name of cookie to delete, or Bool true to delete all + * @paramater Object options - optional list of cookie options to specify ( path, domain ) + * @return void + */ + Constructor.prototype.del = function( cookieName, options ) + { + var allCookies, name; + + allCookies = {}; + + if( typeof options !== 'object' || options === null ) + { + options = {}; + } + + if( typeof cookieName === 'boolean' && cookieName === true ) + { + allCookies = this.get(); + } + else if( typeof cookieName === 'string' ) + { + allCookies[cookieName] = true; + } + + for( name in allCookies ) + { + if( Object.prototype.hasOwnProperty.call( allCookies, name ) && typeof name === 'string' && name !== '' ) + { + this.set( name, null, options ); + } + } + }; + /** + * test - test whether the browser is accepting cookies + * + * @access public + * @return Boolean + */ + Constructor.prototype.test = function() + { + var returnValue, testName, testValue; + + testName = 'cookiesCT'; + testValue = 'data'; + + this.set( testName, testValue ); + + if( this.get( testName ) === testValue ) + { + this.del( testName ); + returnValue = true; + } + + return returnValue; + }; + /** + * setOptions - set default options for calls to cookie methods + * + * @access public + * @param Object options - list of cookie options to specify + * @return void + */ + Constructor.prototype.setOptions = function( options ) + { + if( typeof options !== 'object' ) + { + options = null; + } + + defaultOptions = resolveOptions( options ); + }; + + return new Constructor(); + }() ); + + if( global.jQuery ) + { + ( function( $ ) + { + var NameTokenAttrResolver, cookies, extensions; + + NameTokenAttrResolver = function() + { + var nameTokenAttrs = ['name', 'id']; + this.current = null; + this.nextAttrName = function() + { + this.current = nameTokenAttrs.shift(); + return !! this.current; + }; + }; + + cookies = $.cookies = jaaulde.utils.cookies; + + extensions = { + /** + * $( 'selector' ).cookify - set the value of an input field, or the innerHTML of an element, to a cookie by the name or id of the field or element + * (field or element MUST have name or id attribute) + * + * @access public + * @param options OBJECT - list of cookie options to specify + * @return jQuery + */ + cookify: function( options ) + { + this + .not( ':input' ) + /* + Iterate non input elements + */ + .each( function() + { + var $this, NTAR, nameToken, value; + + $this = $( this ); + + NTAR = new NameTokenAttrResolver(); + + while( NTAR.nextAttrName() ) + { + nameToken = $this.attr( NTAR.current ); + if( typeof nameToken === 'string' && nameToken !== '' ) + { + value = $this.html(); + + cookies.set( + nameToken, + ( typeof value === 'string' && value !== '' ) ? value : null, + options + ); + + break; + } + } + } ) + .end() + .filter( ':input') + .filter( ':radio' ) + /* + Iterate radio inputs + */ + .each( function() + { + + } ) + .end() + .filter( ':checkbox' ) + /* + Iterate checkbox inputs + */ + .each( function() + { + + } ) + .end() + .not( ':radio, :checkbox' ) + /* + Iterate all other inputs + */ + .each( function() + { + var $this, NTAR, nameToken, value; + + $this = $( this ); + + NTAR = new NameTokenAttrResolver(); + + while( NTAR.nextAttrName() ) + { + nameToken = $this.attr( NTAR.current ); + if( typeof nameToken === 'string' && nameToken !== '' ) + { + value = $this.val(); + + cookies.set( + nameToken, + ( typeof value === 'string' && value !== '' ) ? value : null, + options + ); + + break; + } + } + } ); + + return this; + }, + /** + * $( 'selector' ).cookieFill - set the value of an input field or the innerHTML of an element from a cookie by the name or id of the field or element + * + * @access public + * @return jQuery + */ + cookieFill: function() + { + this + .not( ':input' ) + /* + Iterate non input elements + */ + .each( function() + { + var $this, NTAR, nameToken, value; + + $this = $( this ); + + NTAR = new NameTokenAttrResolver(); + + while( NTAR.nextAttrName() ) + { + nameToken = $this.attr( NTAR.current ); + if( typeof nameToken === 'string' && nameToken !== '' ) + { + value = cookies.get( nameToken ); + if( value !== null ) + { + $this.html( value ); + } + + break; + } + } + } ) + .end() + .filter( ':input') + .filter( ':radio' ) + /* + Iterate radio inputs + */ + .each( function() + { + + } ) + .end() + .filter( ':checkbox' ) + /* + Iterate checkbox inputs + */ + .each( function() + { + + } ) + .end() + .not( ':radio, :checkbox' ) + /* + Iterate all other inputs + */ + .each( function() + { + var $this, NTAR, nameToken, value; + + $this = $( this ); + + NTAR = new NameTokenAttrResolver(); + + while( NTAR.nextAttrName() ) + { + nameToken = $this.attr( NTAR.current ); + if( typeof nameToken === 'string' && nameToken !== '' ) + { + value = cookies.get( nameToken ); + if( value !== null ) + { + $this.val( value ); + } + + break; + } + } + } ); + + return this; + }, + /** + * $( 'selector' ).cookieBind - call cookie fill on matching elements, and bind their change events to cookify() + * + * @access public + * @param options OBJECT - list of cookie options to specify + * @return jQuery + */ + cookieBind: function( options ) + { + return this.each( function() + { + var $this = $( this ); + $this.cookieFill().change( function() + { + $this.cookify( options ); + } ); + } ); + } + }; + + $.each( extensions, function( i ) + { + $.fn[i] = this; + } ); + + }( global.jQuery ) ); + } +}( window ) ); \ No newline at end of file