diff --git a/README.md b/README.md index d4144f2..e80c15f 100644 --- a/README.md +++ b/README.md @@ -22,31 +22,57 @@ Download memorystorage.min.js, place it in a folder `lib` in the root of your we ``` ## Create a memory storage object +The `MemoryStorage` function creates (or returns) a storage object implementing the W3C Web Storage API. +By default, scripts share a `global` storage object, so scripts can access and mutate each other's store +object. To have MemoryStorage create a storage object that is isolated from other scripts, you pass in +a unique ID which acts as a namespace: + +```javascript +var isolated = new MemoryStorage('my-app'); // isolated from other scripts, recommended. +``` + +If you don't pass in an ID, or use the ID `'global'`, you get a globally shared storage object: + +```javascript +var global = new MemoryStorage(); // will default to a globally shared storage object. +var global2 = new MemoryStorage('global'); // effectively same as above +``` + +For your convenience, the constructor permits `new`-less invocation: +```javascript +var store = MemoryStorage('my-store'); +var global = MemoryStorage(); +``` + +Instances of `MemoryStorage` expose an immutable `id` property that is set to +the id the store was created with: + ```javascript -var memoryStorage = new MemoryStorage('my-app'); +alert(store.id); // alerts 'my-store' +alert(global.id); // alerts 'global' ``` ## Use it ```javascript -memoryStorage.setItem('myString', 'Hello MemoryStorage!'); -memoryStorage.myObject = JSON.stringify({my: 'object'})); -alert(memoryStorage.getItem('My string')); // alerts 'Hello MemoryStorage!' -alert(memoryStorage['My string']); // alerts 'Hello MemoryStorage!' -alert(memoryStorage.length); // alerts '2' -alert(memoryStorage.key(1)); // alerts 'My object' -memoryStorage.removeItem('My string'); -alert(memoryStorage.length); // alerts '1' -memoryStorage.clear(); -alert(memoryStorage.length); // alerts '0' +store.setItem('myString', 'Hello MemoryStorage!'); +store.myObject = JSON.stringify({my: 'object'})); +alert(store.getItem('My string')); // alerts 'Hello MemoryStorage!' +alert(store['My string']); // alerts 'Hello MemoryStorage!' +alert(store.length); // alerts '2' +alert(store.key(1)); // alerts 'My object' +store.removeItem('My string'); +alert(store.length); // alerts '1' +store.clear(); +alert(store.length); // alerts '0' ``` ## Beyond the Web Storage API -MemoryStorage is type-agnosic; it doesn't care about the type of data you store. +MemoryStorage is type-agnostic; it doesn't care about the type of data you store. If you want to remain within the Web Storage API, you should only read and write strings, however if you want you can store other types just as well: ```javascript -memoryStorage.myObject = {my: 'object'}; -alert(memoryStorage.myObject.my); // alerts 'object' +store.myObject = {my: 'object'}; +alert(store.myObject.my); // alerts 'object' var tree = { nested: { objects: { @@ -54,8 +80,12 @@ var tree = { } } } -memoryStorage.setItem('tree', tree); -alert(memoryStorage.tree.nested.objects.working); // alerts 'Sure!' +store.setItem('tree', tree); +alert(store.tree.nested.objects.working); // alerts 'Sure!' ``` +## Copyright +Copyright 2015 by Stijn de Witt. Some rights reserved. +## License +Licensed under the [Creative Commons Attribution 4.0 International (CC-BY-4.0)](https://creativecommons.org/licenses/by/4.0/) Open Source license. \ No newline at end of file diff --git a/dist/memorystorage.min.js b/dist/memorystorage.min.js index 68b3827..57ec285 100644 --- a/dist/memorystorage.min.js +++ b/dist/memorystorage.min.js @@ -1,3 +1,3 @@ -/*! [memorystorage 0.9.5](http://download.github.io/memorystorage) Copyright 2015 by [Stijn de Witt](http://StijnDeWitt.com). Some rights reserved. License: [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/) */ -!function(u,m,d){"function"==typeof define&&define.amd?define(d):"object"==typeof exports?module.exports=d():u[m]=d()}(this,"MemoryStorage",function(){"use strict";function MemoryStorage(f){f=f||"global";var g=e[f];if(g)return g;g=e[f]=this;var h={};return Object.defineProperty(this,c,{enumerable:!1,get:function(){return h}}),Object.defineProperty(this,"length",{enumerable:!0,get:function(){return Object.keys(this).length+Object.keys(this[c]).length-b}}),this.getItem=function(b){return b in a?this[c][b]:this[b]},this.setItem=function(b,e){b in a?this[c][b]=e:this[b]=e},this.removeItem=function(b){b in a?delete this[c][b]:delete this[b]},this.key=function(b){var e=Object.keys(this).concat(Object.keys(this[c]));return e=e.filter(function(b){return!(b in a)}),b>=0&&b=0&&bSource: memorystorage.js }(this, 'MemoryStorage', function(){ 'use strict'; - var API = {'clear':1, 'getItem':1, 'key':1, 'length':1, 'removeItem':1, 'setItem':1}, + // API methods and properties will be cloaked + var API = {'clear':1, 'getItem':1, 'id':1, 'key':1, 'length':1, 'removeItem':1, 'setItem':1}, API_LENGTH = Object.keys(API).length, CLOAK = '__memorystorage_cloaked_items__'; - // Used to store all data + // Used to store all memorystorage objects var storage = {}; /** @module memorystorage */ @@ -97,41 +98,55 @@

Source: memorystorage.js

* @class */ function MemoryStorage(id) { + // make sure id is assigned id = id || 'global'; + // try to get existing store var result = storage[id]; + // return it if found if (result) {return result;} + // make sure there is no harm in leaving out new in invocations to MemoryStorage + if (! (this instanceof MemoryStorage)) {return new MemoryStorage(id);} + + // create a new store and save a ref to it so we can get it back later result = storage[id] = this; // create a space to store 'cloaked' key/values: items that have a key // that collides with Web Storage API method names. var cloaked = {}; - Object.defineProperty(this, CLOAK, { + Object.defineProperty(result, CLOAK, { enumerable: false, get: function(){return cloaked;} }); - Object.defineProperty(this, 'length', { + // Allow client code to read the id + Object.defineProperty(result, 'id', { + enumerable: true, + get: function(){return id;} + }); + // Create the length property + Object.defineProperty(result, 'length', { enumerable: true, get: function(){ return Object.keys(this).length + Object.keys(this[CLOAK]).length - API_LENGTH; } }); - this.getItem = function MemoryStorage_getItem(key) { + // Create API methods + result.getItem = function MemoryStorage_getItem(key) { return key in API ? this[CLOAK][key] : this[key]; }; - this.setItem = function MemoryStorage_setItem(key, val) { + result.setItem = function MemoryStorage_setItem(key, val) { if (key in API) {this[CLOAK][key] = val;} else {this[key] = val;} }; - this.removeItem = function MemoryStorage_removeItem(key) { + result.removeItem = function MemoryStorage_removeItem(key) { if (key in API) {delete this[CLOAK][key];} else {delete this[key];} }; - this.key = function MemoryStorage_key(idx) { + result.key = function MemoryStorage_key(idx) { var keys = Object.keys(this).concat(Object.keys(this[CLOAK])); keys = keys.filter(function(x){return !(x in API);}); return idx >= 0 && idx < keys.length ? keys[idx] : null; }; - this.clear = function MemoryStorage_clear() { + result.clear = function MemoryStorage_clear() { var keys = Object.keys(this).filter(function(x){return !(x in API);}); for (var i=0,key; key=keys[i]; i++) { if (! (key in API)) {delete this[key];} diff --git a/doc/module-memorystorage.MemoryStorage.html b/doc/module-memorystorage.MemoryStorage.html index c7edb4c..3b238af 100644 --- a/doc/module-memorystorage.MemoryStorage.html +++ b/doc/module-memorystorage.MemoryStorage.html @@ -179,7 +179,7 @@
Parameters:
diff --git a/doc/module-memorystorage.html b/doc/module-memorystorage.html index 9d3a5ff..fdf337b 100644 --- a/doc/module-memorystorage.html +++ b/doc/module-memorystorage.html @@ -103,7 +103,7 @@

Module: memorystorage

diff --git a/package.json b/package.json index 086e359..521092f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "memorystorage", - "version": "0.9.6", + "version": "0.9.7", "description": "Memory-backed implementation of the Web Storage API", "main": "src/memorystorage.js", "dist": { diff --git a/src/memorystorage.js b/src/memorystorage.js index 311b7db..070e981 100644 --- a/src/memorystorage.js +++ b/src/memorystorage.js @@ -11,11 +11,12 @@ }(this, 'MemoryStorage', function(){ 'use strict'; - var API = {'clear':1, 'getItem':1, 'key':1, 'length':1, 'removeItem':1, 'setItem':1}, + // API methods and properties will be cloaked + var API = {'clear':1, 'getItem':1, 'id':1, 'key':1, 'length':1, 'removeItem':1, 'setItem':1}, API_LENGTH = Object.keys(API).length, CLOAK = '__memorystorage_cloaked_items__'; - // Used to store all data + // Used to store all memorystorage objects var storage = {}; /** @module memorystorage */ @@ -36,41 +37,55 @@ * @class */ function MemoryStorage(id) { + // make sure id is assigned id = id || 'global'; + // try to get existing store var result = storage[id]; + // return it if found if (result) {return result;} + // make sure there is no harm in leaving out new in invocations to MemoryStorage + if (! (this instanceof MemoryStorage)) {return new MemoryStorage(id);} + + // create a new store and save a ref to it so we can get it back later result = storage[id] = this; // create a space to store 'cloaked' key/values: items that have a key // that collides with Web Storage API method names. var cloaked = {}; - Object.defineProperty(this, CLOAK, { + Object.defineProperty(result, CLOAK, { enumerable: false, get: function(){return cloaked;} }); - Object.defineProperty(this, 'length', { + // Allow client code to read the id + Object.defineProperty(result, 'id', { + enumerable: true, + get: function(){return id;} + }); + // Create the length property + Object.defineProperty(result, 'length', { enumerable: true, get: function(){ return Object.keys(this).length + Object.keys(this[CLOAK]).length - API_LENGTH; } }); - this.getItem = function MemoryStorage_getItem(key) { + // Create API methods + result.getItem = function MemoryStorage_getItem(key) { return key in API ? this[CLOAK][key] : this[key]; }; - this.setItem = function MemoryStorage_setItem(key, val) { + result.setItem = function MemoryStorage_setItem(key, val) { if (key in API) {this[CLOAK][key] = val;} else {this[key] = val;} }; - this.removeItem = function MemoryStorage_removeItem(key) { + result.removeItem = function MemoryStorage_removeItem(key) { if (key in API) {delete this[CLOAK][key];} else {delete this[key];} }; - this.key = function MemoryStorage_key(idx) { + result.key = function MemoryStorage_key(idx) { var keys = Object.keys(this).concat(Object.keys(this[CLOAK])); keys = keys.filter(function(x){return !(x in API);}); return idx >= 0 && idx < keys.length ? keys[idx] : null; }; - this.clear = function MemoryStorage_clear() { + result.clear = function MemoryStorage_clear() { var keys = Object.keys(this).filter(function(x){return !(x in API);}); for (var i=0,key; key=keys[i]; i++) { if (! (key in API)) {delete this[key];} diff --git a/tests/index.html b/tests/index.html index ba95c03..5f21dea 100644 --- a/tests/index.html +++ b/tests/index.html @@ -2,10 +2,10 @@ MemoryStorage Tests - + - Restart + Restart

MemoryStorage Tests

Test code diff --git a/tests/test.js b/tests/test.js index 1f83b22..19d5e46 100644 --- a/tests/test.js +++ b/tests/test.js @@ -15,7 +15,7 @@ QUnit.test("W3C Web Storage API Compliance Test", function( assert ) { assert.ok(store.length===2, 'value added correctly with index operators'); store.setItem('test2', 'data2'); assert.ok(store.length===3, 'three items added to store'); - assert.ok(Object.keys(store).length == (6+3), "store has 9 enumerable properties (6 api methods + 3 stored items)"); + assert.ok(Object.keys(store).length == (7+3), "store has 10 enumerable properties (id, 6 api methods + 3 stored items)"); assert.ok(store.getItem('test1')==='data1' && store.getItem('test2')==='data2', "retrieved values matches stored values"); var keyOrderBefore = ''; for (var i=0; i