├── .gitignore ├── .jshintignore ├── .jshintrc ├── .tm_properties ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Gruntfile.js ├── MIT-LICENSE.txt ├── README.md ├── bower.json ├── component.json ├── cookie.jquery.json ├── package.json ├── src ├── .jshintrc └── jquery.cookie.js └── test ├── .jshintrc ├── index.html ├── malformed_cookie.html └── tests.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | .sizecache.json 4 | *.log* 5 | -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules 3 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "curly": true, 3 | "eqeqeq": true, 4 | "expr": true, 5 | // "maxlen": 130, 6 | "newcap": true, 7 | "noarg": true, 8 | "nonbsp": true, 9 | "trailing": true, 10 | "undef": true, 11 | "unused": true 12 | } 13 | -------------------------------------------------------------------------------- /.tm_properties: -------------------------------------------------------------------------------- 1 | softTabs = false 2 | tabSize = 2 3 | 4 | [ text.plain ] 5 | softWrap = true 6 | wrapColumn = "Use Window Frame" 7 | softTabs = true 8 | tabSize = 4 9 | 10 | [ "*.md" ] 11 | fileType = "text.plain" 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 0.10 4 | before_script: 5 | - npm install -g grunt-cli 6 | script: grunt ci --verbose 7 | env: 8 | global: 9 | - secure: HRae0kyIDDuhonvMi2SfEl1WJb4K/wX8WmzT9YkxFbmWwLjiOMkmqyuEyi76DbTC1cb9o7WwGVgbP1DhSm6n6m0Lz+PSzpprBN4QZuJc56jcc+tBA6gM81hyUufaTT0yUWz112Bu06kWIAs44w5PtG0FYZR0CuIN8fQvZi8fXCQ= 10 | - secure: c+M5ECIfxDcVrr+ZlqgpGjv8kVM/hxiz3ACMCn4ZkDiaeq4Rw0wWIGZYL6aV5fhsoHgzEQ/XQPca8xKs3Umr7R3b6Vr3AEyFnW+LP67K/1Qbz4Pi3PvhDH/h4rvK7fOoTqTDCVVDEH3v4pefsz2VaKemG4iBKxrcof5aR4Rjopk= 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | HEAD 2 | ----- 3 | 4 | 1.4.1 5 | ----- 6 | - Added support for CommonJS. 7 | 8 | - Added support for package managers: Jam (http://jamjs.org), volo (http://volojs.org), Component (http://component.io), jspm (http://jspm.io). 9 | 10 | - The expires option now interpretes fractions of numbers (e.g. days) correctly. 11 | 12 | 1.4.0 13 | ----- 14 | - Support for AMD. 15 | 16 | - Removed deprecated method `$.cookie('name', null)` for deleting a cookie, 17 | use `$.removeCookie('name')`. 18 | 19 | - `$.cookie('name')` now returns `undefined` in case such cookie does not exist 20 | (was `null`). Because the return value is still falsy, testing for existence 21 | of a cookie like `if ( $.cookie('foo') )` keeps working without change. 22 | 23 | - Renamed bower package definition (component.json -> bower.json) for usage 24 | with up-to-date bower. 25 | 26 | - Badly encoded cookies no longer throw exception upon reading but do return 27 | undefined (similar to how we handle JSON parse errors with json = true). 28 | 29 | - Added conversion function as optional last argument for reading, 30 | so that values can be changed to a different representation easily on the fly. 31 | Useful for parsing numbers for instance: 32 | 33 | ```javascript 34 | $.cookie('foo', '42'); 35 | $.cookie('foo', Number); // => 42 36 | ``` 37 | 38 | 1.3.1 39 | ----- 40 | - Fixed issue where it was no longer possible to check for an arbitrary cookie, 41 | while json is set to true, there was a SyntaxError thrown from JSON.parse. 42 | 43 | - Fixed issue where RFC 2068 decoded cookies were not properly read. 44 | 45 | 1.3.0 46 | ----- 47 | - Configuration options: `raw`, `json`. Replaces raw option, becomes config: 48 | 49 | ```javascript 50 | $.cookie.raw = true; // bypass encoding/decoding the cookie value 51 | $.cookie.json = true; // automatically JSON stringify/parse value 52 | ``` 53 | 54 | Thus the default options now cleanly contain cookie attributes only. 55 | 56 | - Removing licensing under GPL Version 2, the plugin is now released under MIT License only 57 | (keeping it simple and following the jQuery library itself here). 58 | 59 | - Bugfix: Properly handle RFC 2068 quoted cookie values. 60 | 61 | - Added component.json for bower. 62 | 63 | - Added jQuery plugin package manifest. 64 | 65 | - `$.cookie()` returns all available cookies. 66 | 67 | 1.2.0 68 | ----- 69 | - Adding `$.removeCookie('foo')` for deleting a cookie, using `$.cookie('foo', null)` is now deprecated. 70 | 71 | 1.1 72 | --- 73 | - Adding default options. 74 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ##Issues 2 | 3 | - Report issues or feature requests on [GitHub Issues](https://github.com/carhartl/jquery-cookie/issues). 4 | - If reporting a bug, please add a [simplified example](http://sscce.org/). 5 | 6 | ##Pull requests 7 | - Create a new topic branch for every separate change you make. 8 | - Create a test case if you are fixing a bug or implementing an important feature. 9 | - Make sure the build runs successfully. 10 | 11 | ## Development 12 | 13 | ###Tools 14 | We use the following tools for development: 15 | 16 | - [Qunit](http://qunitjs.com/) for tests. 17 | - [NodeJS](http://nodejs.org/download/) required to run grunt. 18 | - [Grunt](http://gruntjs.com/getting-started) for task management. 19 | 20 | ###Getting started 21 | Install [NodeJS](http://nodejs.org/). 22 | Install globally grunt-cli using the following command: 23 | 24 | $ npm install -g grunt-cli 25 | 26 | Browse to the project root directory and install the dev dependencies: 27 | 28 | $ npm install -d 29 | 30 | To execute the build and tests run the following command in the root of the project: 31 | 32 | $ grunt 33 | 34 | You should see a green message in the console: 35 | 36 | Done, without errors. 37 | 38 | ###Tests 39 | You can also run the tests in the browser. 40 | Start a test server from the project root: 41 | 42 | $ grunt connect:tests 43 | 44 | This will automatically open the test suite at http://127.0.0.1:9998 in the default browser, with livereload enabled. 45 | 46 | _Note: we recommend cleaning all the browser cookies before running the tests, that can avoid false positive failures._ 47 | 48 | ###Automatic build 49 | You can build automatically after a file change using the following command: 50 | 51 | $ grunt watch 52 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, quotmark:single */ 2 | 'use strict'; 3 | 4 | module.exports = function (grunt) { 5 | 6 | grunt.initConfig({ 7 | pkg: grunt.file.readJSON('package.json'), 8 | qunit: { 9 | all: 'test/index.html' 10 | }, 11 | jshint: { 12 | options: { 13 | jshintrc: true 14 | }, 15 | grunt: 'Gruntfile.js', 16 | source: 'src/**/*.js', 17 | tests: 'test/**/*.js' 18 | }, 19 | uglify: { 20 | options: { 21 | banner: '/*! <%= pkg.name %> v<%= pkg.version %> | <%= pkg.license %> */\n' 22 | }, 23 | build: { 24 | files: { 25 | 'build/jquery.cookie-<%= pkg.version %>.min.js': 'src/jquery.cookie.js' 26 | } 27 | } 28 | }, 29 | watch: { 30 | options: { 31 | livereload: true 32 | }, 33 | files: '{src,test}/**/*.js', 34 | tasks: 'default' 35 | }, 36 | compare_size: { 37 | files: [ 38 | 'build/jquery.cookie-<%= pkg.version %>.min.js', 39 | 'src/jquery.cookie.js' 40 | ], 41 | options: { 42 | compress: { 43 | gz: function (fileContents) { 44 | return require('gzip-js').zip(fileContents, {}).length; 45 | } 46 | } 47 | } 48 | }, 49 | connect: { 50 | saucelabs: { 51 | options: { 52 | port: 9999, 53 | base: ['.', 'test'] 54 | } 55 | }, 56 | tests: { 57 | options: { 58 | port: 9998, 59 | base: ['.', 'test'], 60 | open: 'http://127.0.0.1:9998', 61 | keepalive: true, 62 | livereload: true 63 | } 64 | } 65 | }, 66 | 'saucelabs-qunit': { 67 | all: { 68 | options: { 69 | urls: ['http://127.0.0.1:9999'], 70 | build: process.env.TRAVIS_JOB_ID, 71 | browsers: [ 72 | // iOS 73 | { 74 | browserName: 'iphone', 75 | platform: 'OS X 10.9', 76 | version: '7.1' 77 | }, 78 | { 79 | browserName: 'ipad', 80 | platform: 'OS X 10.9', 81 | version: '7.1' 82 | }, 83 | // Android 84 | { 85 | browserName: 'android', 86 | platform: 'Linux', 87 | version: '4.3' 88 | }, 89 | // OS X 90 | { 91 | browserName: 'safari', 92 | platform: 'OS X 10.9', 93 | version: '7' 94 | }, 95 | { 96 | browserName: 'safari', 97 | platform: 'OS X 10.8', 98 | version: '6' 99 | }, 100 | { 101 | browserName: 'firefox', 102 | platform: 'OS X 10.9', 103 | version: '28' 104 | }, 105 | // Windows 106 | { 107 | browserName: 'internet explorer', 108 | platform: 'Windows 8.1', 109 | version: '11' 110 | }, 111 | { 112 | browserName: 'internet explorer', 113 | platform: 'Windows 8', 114 | version: '10' 115 | }, 116 | { 117 | browserName: 'internet explorer', 118 | platform: 'Windows 7', 119 | version: '11' 120 | }, 121 | { 122 | browserName: 'internet explorer', 123 | platform: 'Windows 7', 124 | version: '10' 125 | }, 126 | { 127 | browserName: 'internet explorer', 128 | platform: 'Windows 7', 129 | version: '9' 130 | }, 131 | { 132 | browserName: 'internet explorer', 133 | platform: 'Windows 7', 134 | version: '8' 135 | }, 136 | { 137 | browserName: 'firefox', 138 | platform: 'Windows 7', 139 | version: '29' 140 | }, 141 | { 142 | browserName: 'chrome', 143 | platform: 'Windows 7', 144 | version: '34' 145 | }, 146 | // Linux 147 | { 148 | browserName: 'firefox', 149 | platform: 'Linux', 150 | version: '29' 151 | } 152 | ] 153 | } 154 | } 155 | } 156 | }); 157 | 158 | // Loading dependencies 159 | for (var key in grunt.file.readJSON('package.json').devDependencies) { 160 | if (key !== 'grunt' && key.indexOf('grunt') === 0) { 161 | grunt.loadNpmTasks(key); 162 | } 163 | } 164 | 165 | grunt.registerTask('default', ['jshint', 'qunit', 'uglify', 'compare_size']); 166 | grunt.registerTask('saucelabs', ['connect:saucelabs', 'saucelabs-qunit']); 167 | grunt.registerTask('ci', ['jshint', 'qunit', 'saucelabs']); 168 | }; 169 | -------------------------------------------------------------------------------- /MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2014 Klaus Hartl 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IMPORTANT! 2 | 3 | This project was moved to https://github.com/js-cookie/js-cookie, check [the discussion](https://github.com/carhartl/jquery-cookie/issues/349). 4 | 5 | New issues should be opened at https://github.com/js-cookie/js-cookie/issues 6 | 7 | # jquery.cookie [![Build Status](https://travis-ci.org/carhartl/jquery-cookie.png?branch=master)](https://travis-ci.org/carhartl/jquery-cookie) [![Code Climate](https://codeclimate.com/github/carhartl/jquery-cookie.png)](https://codeclimate.com/github/carhartl/jquery-cookie) 8 | 9 | A simple, lightweight jQuery plugin for reading, writing and deleting cookies. 10 | 11 | **If you're viewing this, you're reading the documentation for the old repository. 12 | [View documentation for the latest backwards compatible release (1.5.1).](https://github.com/js-cookie/js-cookie/tree/v1.5.1)** 13 | 14 | ## Build Status Matrix 15 | 16 | [![Selenium Test Status](https://saucelabs.com/browser-matrix/jquery-cookie.svg)](https://saucelabs.com/u/jquery-cookie) 17 | 18 | ## Installation 19 | 20 | Include script *after* the jQuery library (unless you are packaging scripts somehow else): 21 | 22 | ```html 23 | 24 | ``` 25 | 26 | **Do not include the script directly from GitHub (http://raw.github.com/...).** The file is being served as text/plain and as such being blocked 27 | in Internet Explorer on Windows 7 for instance (because of the wrong MIME type). Bottom line: GitHub is not a CDN. 28 | 29 | The plugin can also be loaded as AMD or CommonJS module. 30 | 31 | ## Usage 32 | 33 | Create session cookie: 34 | 35 | ```javascript 36 | $.cookie('name', 'value'); 37 | ``` 38 | 39 | Create expiring cookie, 7 days from then: 40 | 41 | ```javascript 42 | $.cookie('name', 'value', { expires: 7 }); 43 | ``` 44 | 45 | Create expiring cookie, valid across entire site: 46 | 47 | ```javascript 48 | $.cookie('name', 'value', { expires: 7, path: '/' }); 49 | ``` 50 | 51 | Read cookie: 52 | 53 | ```javascript 54 | $.cookie('name'); // => "value" 55 | $.cookie('nothing'); // => undefined 56 | ``` 57 | 58 | Read all available cookies: 59 | 60 | ```javascript 61 | $.cookie(); // => { "name": "value" } 62 | ``` 63 | 64 | Delete cookie: 65 | 66 | ```javascript 67 | // Returns true when cookie was successfully deleted, otherwise false 68 | $.removeCookie('name'); // => true 69 | $.removeCookie('nothing'); // => false 70 | 71 | // Need to use the same attributes (path, domain) as what the cookie was written with 72 | $.cookie('name', 'value', { path: '/' }); 73 | // This won't work! 74 | $.removeCookie('name'); // => false 75 | // This will work! 76 | $.removeCookie('name', { path: '/' }); // => true 77 | ``` 78 | 79 | *Note: when deleting a cookie, you must pass the exact same path, domain and secure options that were used to set the cookie, unless you're relying on the default options that is.* 80 | 81 | ## Configuration 82 | 83 | ### raw 84 | 85 | By default the cookie value is encoded/decoded when writing/reading, using `encodeURIComponent`/`decodeURIComponent`. Bypass this by setting raw to true: 86 | 87 | ```javascript 88 | $.cookie.raw = true; 89 | ``` 90 | 91 | ### json 92 | 93 | Turn on automatic storage of JSON objects passed as the cookie value. Assumes `JSON.stringify` and `JSON.parse`: 94 | 95 | ```javascript 96 | $.cookie.json = true; 97 | ``` 98 | 99 | ## Cookie Options 100 | 101 | Cookie attributes can be set globally by setting properties of the `$.cookie.defaults` object or individually for each call to `$.cookie()` by passing a plain object to the options argument. Per-call options override the default options. 102 | 103 | ### expires 104 | 105 | expires: 365 106 | 107 | Define lifetime of the cookie. Value can be a `Number` which will be interpreted as days from time of creation or a `Date` object. If omitted, the cookie becomes a session cookie. 108 | 109 | ### path 110 | 111 | path: '/' 112 | 113 | Define the path where the cookie is valid. *By default the path of the cookie is the path of the page where the cookie was created (standard browser behavior).* If you want to make it available for instance across the entire domain use `path: '/'`. Default: path of page where the cookie was created. 114 | 115 | **Note regarding Internet Explorer:** 116 | 117 | > Due to an obscure bug in the underlying WinINET InternetGetCookie implementation, IE’s document.cookie will not return a cookie if it was set with a path attribute containing a filename. 118 | 119 | (From [Internet Explorer Cookie Internals (FAQ)](http://blogs.msdn.com/b/ieinternals/archive/2009/08/20/wininet-ie-cookie-internals-faq.aspx)) 120 | 121 | This means one cannot set a path using `path: window.location.pathname` in case such pathname contains a filename like so: `/check.html` (or at least, such cookie cannot be read correctly). 122 | 123 | ### domain 124 | 125 | domain: 'example.com' 126 | 127 | Define the domain where the cookie is valid. Default: domain of page where the cookie was created. 128 | 129 | ### secure 130 | 131 | secure: true 132 | 133 | If true, the cookie transmission requires a secure protocol (https). Default: `false`. 134 | 135 | ## Converters 136 | 137 | Provide a conversion function as optional last argument for reading, in order to change the cookie's value 138 | to a different representation on the fly. 139 | 140 | Example for parsing a value into a number: 141 | 142 | ```javascript 143 | $.cookie('foo', '42'); 144 | $.cookie('foo', Number); // => 42 145 | ``` 146 | 147 | Dealing with cookies that have been encoded using `escape` (3rd party cookies): 148 | 149 | ```javascript 150 | $.cookie.raw = true; 151 | $.cookie('foo', unescape); 152 | ``` 153 | 154 | You can pass an arbitrary conversion function. 155 | 156 | ## Contributing 157 | 158 | Check out the [Contributing Guidelines](CONTRIBUTING.md) 159 | 160 | ## Authors 161 | 162 | [Klaus Hartl](https://github.com/carhartl) 163 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery.cookie", 3 | "version": "1.4.1", 4 | "main": [ 5 | "src/jquery.cookie.js" 6 | ], 7 | "dependencies": { 8 | "jquery": ">=1.2" 9 | }, 10 | "ignore": [ 11 | "test", 12 | ".*", 13 | "*.json", 14 | "*.md", 15 | "*.txt", 16 | "Gruntfile.js" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery.cookie", 3 | "repo": "carhartl/jquery-cookie", 4 | "description": "A simple, lightweight jQuery plugin for reading, writing and deleting cookies", 5 | "version": "1.4.1", 6 | "keywords": [], 7 | "dependencies": {}, 8 | "development": {}, 9 | "license": "MIT", 10 | "main": "src/jquery.cookie.js", 11 | "scripts": [ 12 | "src/jquery.cookie.js" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /cookie.jquery.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cookie", 3 | "version": "1.4.1", 4 | "title": "jQuery Cookie", 5 | "description": "A simple, lightweight jQuery plugin for reading, writing and deleting cookies.", 6 | "author": { 7 | "name": "Klaus Hartl", 8 | "url": "https://github.com/carhartl" 9 | }, 10 | "maintainers": [ 11 | { 12 | "name": "Klaus Hartl", 13 | "url": "https://github.com/carhartl" 14 | }, 15 | { 16 | "name": "Fagner Martins", 17 | "url": "https://github.com/FagnerMartinsBrack" 18 | } 19 | ], 20 | "licenses": [ 21 | { 22 | "type": "MIT", 23 | "url": "https://raw.github.com/carhartl/jquery-cookie/master/MIT-LICENSE.txt" 24 | } 25 | ], 26 | "dependencies": { 27 | "jquery": ">=1.2" 28 | }, 29 | "bugs": "https://github.com/carhartl/jquery-cookie/issues", 30 | "homepage": "https://github.com/carhartl/jquery-cookie", 31 | "docs": "https://github.com/carhartl/jquery-cookie#readme" 32 | } 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery.cookie", 3 | "version": "1.4.1", 4 | "description": "A simple, lightweight jQuery plugin for reading, writing and deleting cookies.", 5 | "main": "src/jquery.cookie.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "grunt" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git://github.com/carhartl/jquery-cookie.git" 15 | }, 16 | "author": "Klaus Hartl", 17 | "license": "MIT", 18 | "gitHead": "bd3c9713222bace68d25fe2128c0f8633cad1269", 19 | "readmeFilename": "README.md", 20 | "devDependencies": { 21 | "grunt": "~0.4.1", 22 | "grunt-contrib-jshint": "~0.10.0", 23 | "grunt-contrib-uglify": "~0.2.0", 24 | "grunt-contrib-qunit": "~0.2.0", 25 | "grunt-contrib-watch": "~0.6.1", 26 | "grunt-compare-size": "~0.4.0", 27 | "grunt-saucelabs": "~7.0.0", 28 | "grunt-contrib-connect": "~0.7.1", 29 | "gzip-js": "~0.3.0" 30 | }, 31 | "volo": { 32 | "url": "https://raw.github.com/carhartl/jquery-cookie/v{version}/src/jquery.cookie.js" 33 | }, 34 | "jspm": { 35 | "main": "jquery.cookie", 36 | "files": ["src/jquery.cookie.js"], 37 | "buildConfig": { 38 | "uglify": true 39 | } 40 | }, 41 | "jam": { 42 | "dependencies": { 43 | "jquery": ">=1.2" 44 | }, 45 | "main": "src/jquery.cookie.js", 46 | "include": [ 47 | "src/jquery.cookie.js" 48 | ] 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "browser": true, 3 | "camelcase": true, 4 | "jquery": true, 5 | "quotmark": "single", 6 | "globals": { 7 | "define": true, 8 | "module": true, 9 | "require": true 10 | }, 11 | 12 | "extends": "../.jshintrc" 13 | } 14 | -------------------------------------------------------------------------------- /src/jquery.cookie.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery Cookie Plugin v1.4.1 3 | * https://github.com/carhartl/jquery-cookie 4 | * 5 | * Copyright 2006, 2014 Klaus Hartl 6 | * Released under the MIT license 7 | */ 8 | (function (factory) { 9 | if (typeof define === 'function' && define.amd) { 10 | // AMD (Register as an anonymous module) 11 | define(['jquery'], factory); 12 | } else if (typeof exports === 'object') { 13 | // Node/CommonJS 14 | module.exports = factory(require('jquery')); 15 | } else { 16 | // Browser globals 17 | factory(jQuery); 18 | } 19 | }(function ($) { 20 | 21 | var pluses = /\+/g; 22 | 23 | function encode(s) { 24 | return config.raw ? s : encodeURIComponent(s); 25 | } 26 | 27 | function decode(s) { 28 | return config.raw ? s : decodeURIComponent(s); 29 | } 30 | 31 | function stringifyCookieValue(value) { 32 | return encode(config.json ? JSON.stringify(value) : String(value)); 33 | } 34 | 35 | function parseCookieValue(s) { 36 | if (s.indexOf('"') === 0) { 37 | // This is a quoted cookie as according to RFC2068, unescape... 38 | s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); 39 | } 40 | 41 | try { 42 | // Replace server-side written pluses with spaces. 43 | // If we can't decode the cookie, ignore it, it's unusable. 44 | // If we can't parse the cookie, ignore it, it's unusable. 45 | s = decodeURIComponent(s.replace(pluses, ' ')); 46 | return config.json ? JSON.parse(s) : s; 47 | } catch(e) {} 48 | } 49 | 50 | function read(s, converter) { 51 | var value = config.raw ? s : parseCookieValue(s); 52 | return $.isFunction(converter) ? converter(value) : value; 53 | } 54 | 55 | var config = $.cookie = function (key, value, options) { 56 | 57 | // Write 58 | 59 | if (arguments.length > 1 && !$.isFunction(value)) { 60 | options = $.extend({}, config.defaults, options); 61 | 62 | if (typeof options.expires === 'number') { 63 | var days = options.expires, t = options.expires = new Date(); 64 | t.setMilliseconds(t.getMilliseconds() + days * 864e+5); 65 | } 66 | 67 | return (document.cookie = [ 68 | encode(key), '=', stringifyCookieValue(value), 69 | options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE 70 | options.path ? '; path=' + options.path : '', 71 | options.domain ? '; domain=' + options.domain : '', 72 | options.secure ? '; secure' : '' 73 | ].join('')); 74 | } 75 | 76 | // Read 77 | 78 | var result = key ? undefined : {}, 79 | // To prevent the for loop in the first place assign an empty array 80 | // in case there are no cookies at all. Also prevents odd result when 81 | // calling $.cookie(). 82 | cookies = document.cookie ? document.cookie.split('; ') : [], 83 | i = 0, 84 | l = cookies.length; 85 | 86 | for (; i < l; i++) { 87 | var parts = cookies[i].split('='), 88 | name = decode(parts.shift()), 89 | cookie = parts.join('='); 90 | 91 | if (key === name) { 92 | // If second argument (value) is a function it's a converter... 93 | result = read(cookie, value); 94 | break; 95 | } 96 | 97 | // Prevent storing a cookie that we couldn't decode. 98 | if (!key && (cookie = read(cookie)) !== undefined) { 99 | result[name] = cookie; 100 | } 101 | } 102 | 103 | return result; 104 | }; 105 | 106 | config.defaults = {}; 107 | 108 | $.removeCookie = function (key, options) { 109 | // Must not alter options, thus extending a fresh object... 110 | $.cookie(key, '', $.extend({}, options, { expires: -1 })); 111 | return !$.cookie(key); 112 | }; 113 | 114 | })); 115 | -------------------------------------------------------------------------------- /test/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "browser": true, 3 | "jquery": true, 4 | "qunit": true, 5 | 6 | "-W053": true, 7 | 8 | "extends": "../.jshintrc" 9 | } 10 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | jquery.cookie Test Suite 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /test/malformed_cookie.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/tests.js: -------------------------------------------------------------------------------- 1 | // Required for exposing test results to the Sauce Labs API. 2 | // Can be removed when the following issue is fixed: 3 | // https://github.com/axemclion/grunt-saucelabs/issues/84 4 | QUnit.done(function (details) { 5 | window.global_test_results = details; 6 | }); 7 | 8 | 9 | var lifecycle = { 10 | teardown: function () { 11 | $.cookie.defaults = {}; 12 | delete $.cookie.raw; 13 | delete $.cookie.json; 14 | $.each($.cookie(), $.removeCookie); 15 | } 16 | }; 17 | 18 | 19 | module('read', lifecycle); 20 | 21 | test('simple value', function () { 22 | expect(1); 23 | document.cookie = 'c=v'; 24 | strictEqual($.cookie('c'), 'v', 'should return value'); 25 | }); 26 | 27 | test('empty value', function () { 28 | expect(1); 29 | // IE saves cookies with empty string as "c; ", e.g. without "=" as opposed to EOMB, which 30 | // resulted in a bug while reading such a cookie. 31 | $.cookie('c', ''); 32 | strictEqual($.cookie('c'), '', 'should return value'); 33 | }); 34 | 35 | test('not existing', function () { 36 | expect(1); 37 | strictEqual($.cookie('whatever'), undefined, 'return undefined'); 38 | }); 39 | 40 | test('RFC 2068 quoted string', function () { 41 | expect(1); 42 | document.cookie = 'c="v@address.com\\"\\\\\\""'; 43 | strictEqual($.cookie('c'), 'v@address.com"\\"', 'should decode RFC 2068 quoted string'); 44 | }); 45 | 46 | test('decode', function () { 47 | expect(1); 48 | document.cookie = encodeURIComponent(' c') + '=' + encodeURIComponent(' v'); 49 | strictEqual($.cookie(' c'), ' v', 'should decode key and value'); 50 | }); 51 | 52 | test('decode pluses to space for server side written cookie', function () { 53 | expect(1); 54 | document.cookie = 'c=foo+bar'; 55 | strictEqual($.cookie('c'), 'foo bar', 'should convert pluses back to space'); 56 | }); 57 | 58 | test('raw = true', function () { 59 | expect(2); 60 | $.cookie.raw = true; 61 | 62 | document.cookie = 'c=%20v'; 63 | strictEqual($.cookie('c'), '%20v', 'should not decode value'); 64 | 65 | // see https://github.com/carhartl/jquery-cookie/issues/50 66 | $.cookie('c', 'foo=bar'); 67 | strictEqual($.cookie('c'), 'foo=bar', 'should include the entire value'); 68 | }); 69 | 70 | test('json = true', function () { 71 | expect(1); 72 | 73 | if ('JSON' in window) { 74 | $.cookie.json = true; 75 | $.cookie('c', { foo: 'bar' }); 76 | deepEqual($.cookie('c'), { foo: 'bar' }, 'should parse JSON'); 77 | } else { 78 | ok(true); 79 | } 80 | }); 81 | 82 | test('not existing with json = true', function () { 83 | expect(1); 84 | 85 | if ('JSON' in window) { 86 | $.cookie.json = true; 87 | strictEqual($.cookie('whatever'), undefined, "won't throw exception"); 88 | } else { 89 | ok(true); 90 | } 91 | }); 92 | 93 | test('string with json = true', function () { 94 | expect(1); 95 | 96 | if ('JSON' in window) { 97 | $.cookie.json = true; 98 | $.cookie('c', 'v'); 99 | strictEqual($.cookie('c'), 'v', 'should return value'); 100 | } else { 101 | ok(true); 102 | } 103 | }); 104 | 105 | test('invalid JSON string with json = true', function () { 106 | expect(1); 107 | 108 | if ('JSON' in window) { 109 | $.cookie('c', 'v'); 110 | $.cookie.json = true; 111 | strictEqual($.cookie('c'), undefined, "won't throw exception, returns undefined"); 112 | } else { 113 | ok(true); 114 | } 115 | }); 116 | 117 | test('invalid URL encoding', function () { 118 | expect(1); 119 | document.cookie = 'bad=foo%'; 120 | strictEqual($.cookie('bad'), undefined, "won't throw exception, returns undefined"); 121 | // Delete manually here because it requires raw === true... 122 | $.cookie.raw = true; 123 | $.removeCookie('bad'); 124 | }); 125 | 126 | asyncTest('malformed cookie value in IE (#88, #117)', function () { 127 | expect(1); 128 | // Sandbox in an iframe so that we can poke around with document.cookie. 129 | var iframe = $('')[0]; 130 | $(iframe).on('load', function () { 131 | start(); 132 | if (iframe.contentWindow.ok) { 133 | strictEqual(iframe.contentWindow.testValue, 'two', 'reads all cookie values, skipping duplicate occurences of "; "'); 134 | } else { 135 | // Skip the test where we can't stub document.cookie using 136 | // Object.defineProperty. Seems to work fine in 137 | // Chrome, Firefox and IE 8+. 138 | ok(true, 'N/A'); 139 | } 140 | }); 141 | document.body.appendChild(iframe); 142 | }); 143 | 144 | test('Call to read all when there are cookies', function () { 145 | $.cookie('c', 'v'); 146 | $.cookie('foo', 'bar'); 147 | deepEqual($.cookie(), { c: 'v', foo: 'bar' }, 'returns object containing all cookies'); 148 | }); 149 | 150 | test('Call to read all when there are no cookies at all', function () { 151 | deepEqual($.cookie(), {}, 'returns empty object'); 152 | }); 153 | 154 | test('Call to read all with json: true', function () { 155 | $.cookie.json = true; 156 | $.cookie('c', { foo: 'bar' }); 157 | deepEqual($.cookie(), { c: { foo: 'bar' } }, 'returns JSON parsed cookies'); 158 | }); 159 | 160 | test('Call to read all with a badly encoded cookie', function () { 161 | expect(1); 162 | document.cookie = 'bad=foo%'; 163 | document.cookie = 'good=foo'; 164 | deepEqual($.cookie(), { good: 'foo' }, 'returns object containing all decodable cookies'); 165 | // Delete manually here because it requires raw === true... 166 | $.cookie.raw = true; 167 | $.removeCookie('bad'); 168 | }); 169 | 170 | 171 | module('write', lifecycle); 172 | 173 | test('String primitive', function () { 174 | expect(1); 175 | $.cookie('c', 'v'); 176 | strictEqual($.cookie('c'), 'v', 'should write value'); 177 | }); 178 | 179 | test('String object', function () { 180 | expect(1); 181 | $.cookie('c', new String('v')); 182 | strictEqual($.cookie('c'), 'v', 'should write value'); 183 | }); 184 | 185 | test('value "[object Object]"', function () { 186 | expect(1); 187 | $.cookie('c', '[object Object]'); 188 | strictEqual($.cookie('c'), '[object Object]', 'should write value'); 189 | }); 190 | 191 | test('number', function () { 192 | expect(1); 193 | $.cookie('c', 1234); 194 | strictEqual($.cookie('c'), '1234', 'should write value'); 195 | }); 196 | 197 | test('null', function () { 198 | expect(1); 199 | $.cookie('c', null); 200 | strictEqual($.cookie('c'), 'null', 'should write value'); 201 | }); 202 | 203 | test('undefined', function () { 204 | expect(1); 205 | $.cookie('c', undefined); 206 | strictEqual($.cookie('c'), 'undefined', 'should write value'); 207 | }); 208 | 209 | test('expires option as days from now', function () { 210 | expect(1); 211 | var sevenDaysFromNow = new Date(); 212 | sevenDaysFromNow.setDate(sevenDaysFromNow.getDate() + 21); 213 | strictEqual($.cookie('c', 'v', { expires: 21 }), 'c=v; expires=' + sevenDaysFromNow.toUTCString(), 214 | 'should write the cookie string with expires'); 215 | }); 216 | 217 | test('expires option as fraction of a day', function () { 218 | expect(1); 219 | 220 | var now = new Date().getTime(); 221 | var expires = Date.parse($.cookie('c', 'v', { expires: 0.5 }).replace(/.+expires=/, '')); 222 | 223 | // When we were using Date.setDate() fractions have been ignored 224 | // and expires resulted in the current date. Allow 1000 milliseconds 225 | // difference for execution time. 226 | ok(expires > now + 1000, 'should write expires attribute with the correct date'); 227 | }); 228 | 229 | test('expires option as Date instance', function () { 230 | expect(1); 231 | var sevenDaysFromNow = new Date(); 232 | sevenDaysFromNow.setDate(sevenDaysFromNow.getDate() + 7); 233 | strictEqual($.cookie('c', 'v', { expires: sevenDaysFromNow }), 'c=v; expires=' + sevenDaysFromNow.toUTCString(), 234 | 'should write the cookie string with expires'); 235 | }); 236 | 237 | test('return value', function () { 238 | expect(1); 239 | strictEqual($.cookie('c', 'v'), 'c=v', 'should return written cookie string'); 240 | }); 241 | 242 | test('defaults', function () { 243 | expect(2); 244 | $.cookie.defaults.path = '/foo'; 245 | ok($.cookie('c', 'v').match(/path=\/foo/), 'should use options from defaults'); 246 | ok($.cookie('c', 'v', { path: '/bar' }).match(/path=\/bar/), 'options argument has precedence'); 247 | }); 248 | 249 | test('raw = true', function () { 250 | expect(1); 251 | $.cookie.raw = true; 252 | strictEqual($.cookie('c[1]', 'v[1]'), 'c[1]=v[1]', 'should not encode'); 253 | // Delete manually here because it requires raw === true... 254 | $.removeCookie('c[1]'); 255 | }); 256 | 257 | test('json = true', function () { 258 | expect(1); 259 | $.cookie.json = true; 260 | 261 | if ('JSON' in window) { 262 | $.cookie('c', { foo: 'bar' }); 263 | strictEqual(document.cookie, 'c=' + encodeURIComponent(JSON.stringify({ foo: 'bar' })), 'should stringify JSON'); 264 | } else { 265 | ok(true); 266 | } 267 | }); 268 | 269 | 270 | module('removeCookie', lifecycle); 271 | 272 | test('deletion', function () { 273 | expect(1); 274 | $.cookie('c', 'v'); 275 | $.removeCookie('c'); 276 | strictEqual(document.cookie, '', 'should delete the cookie'); 277 | }); 278 | 279 | test('when sucessfully deleted', function () { 280 | expect(1); 281 | $.cookie('c', 'v'); 282 | strictEqual($.removeCookie('c'), true, 'returns true'); 283 | }); 284 | 285 | test('when cookie does not exist', function () { 286 | expect(1); 287 | strictEqual($.removeCookie('c'), true, 'returns true'); 288 | }); 289 | 290 | test('when deletion failed', function () { 291 | expect(1); 292 | $.cookie('c', 'v'); 293 | 294 | var originalCookie = $.cookie; 295 | $.cookie = function () { 296 | // Stub deletion... 297 | if (arguments.length === 1) { 298 | return originalCookie.apply(null, arguments); 299 | } 300 | }; 301 | 302 | strictEqual($.removeCookie('c'), false, 'returns false'); 303 | 304 | $.cookie = originalCookie; 305 | }); 306 | 307 | test('with options', function () { 308 | expect(1); 309 | var options = { path: '/' }; 310 | $.cookie('c', 'v', options); 311 | $.removeCookie('c', options); 312 | strictEqual(document.cookie, '', 'should delete the cookie'); 313 | }); 314 | 315 | test('passing options reference', function () { 316 | expect(1); 317 | var options = { path: '/' }; 318 | $.cookie('c', 'v', options); 319 | $.removeCookie('c', options); 320 | deepEqual(options, { path: '/' }, "won't alter options object"); 321 | }); 322 | 323 | test('[] used in name', function () { 324 | expect(1); 325 | $.cookie.raw = true; 326 | document.cookie = 'c[1]=foo'; 327 | $.removeCookie('c[1]'); 328 | strictEqual(document.cookie, '', 'delete the cookie'); 329 | }); 330 | 331 | 332 | module('conversion', lifecycle); 333 | 334 | test('read converter', function() { 335 | expect(1); 336 | $.cookie('c', '1'); 337 | strictEqual($.cookie('c', Number), 1, 'converts read value'); 338 | }); 339 | 340 | test('read converter with raw = true', function() { 341 | expect(1); 342 | $.cookie.raw = true; 343 | $.cookie('c', '1'); 344 | strictEqual($.cookie('c', Number), 1, 'does not decode, but converts read value'); 345 | }); 346 | --------------------------------------------------------------------------------