From 68164d1a4f921a4773c64ef84712d16fdd1c8e06 Mon Sep 17 00:00:00 2001 From: Israel Evans Date: Fri, 27 May 2011 09:45:46 -0700 Subject: [PATCH 1/5] Cleanup and test for localStorage support the Modernizr way Signed-off-by: Israel Evans --- jquery.store.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/jquery.store.js b/jquery.store.js index fab8d0f..bb59d22 100644 --- a/jquery.store.js +++ b/jquery.store.js @@ -24,7 +24,7 @@ * $.storage.get( key ); // retrieves a value * $.storage.set( key, value ); // saves a value * $.storage.del( key ); // deletes a value - * $.storage.flush(); // deletes aall values + * $.storage.flush(); // deletes all values ********************************************************************************** */ @@ -88,7 +88,7 @@ $.store = function( driver, serializers ) { // skip invalid processors if( !$.isFunction( this.init ) ) - return true; // continue; + return; // continue; that.serializers[ key ] = this; that.serializers[ key ].init( that.encoders, that.decoders ); @@ -129,7 +129,7 @@ $.extend( $.store.prototype, { { var serializer = that.serializers[ this + "" ]; if( !serializer || !serializer.encode ) - return true; // continue; + return; // continue; try { value = serializer.encode( value ); @@ -149,8 +149,8 @@ $.extend( $.store.prototype, { { var serializer = that.serializers[ this + "" ]; if( !serializer || !serializer.decode ) - return true; // continue; - + return; // continue; + value = serializer.decode( value ); }); @@ -172,8 +172,8 @@ $.store.drivers = { available: function() { try - { - return !!window.localStorage; + { // localStorage support test, the Modernizr way + return !!localStorage.getItem; } catch(e) { From 2c16812ca75eb9dce8de63af8731f439f33a6686 Mon Sep 17 00:00:00 2001 From: Israel Evans Date: Fri, 27 May 2011 09:53:53 -0700 Subject: [PATCH 2/5] new "sessionStorage" driver and fixed "userData" init() Signed-off-by: Israel Evans --- jquery.store.js | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/jquery.store.js b/jquery.store.js index bb59d22..79da2d4 100644 --- a/jquery.store.js +++ b/jquery.store.js @@ -197,6 +197,49 @@ $.store.drivers = { flush: function() { window.localStorage.clear(); + } + }, + + // Firefox 3.5, Safari 4.0, Chrome 5, Opera 10.5, IE8 + 'sessionStorage': { + // see https://developer.mozilla.org/en/dom/storage#sessionStorage + ident: "$.store.drivers.sessionStorage", + scope: 'window', + available: function() + { + try + { // sessionStorage support test, the Modernizr way + return !!sessionStorage.getItem; + } + catch(e) + { + // Firefox won't allow sessionStorage if DOM Storage disabled + return false; + } + }, + init: $.noop, + get: function( key ) + { + return window.sessionStorage.getItem( key ); + }, + set: function( key, value ) + { + window.sessionStorage.setItem( key, value ); + }, + del: function( key ) + { + window.sessionStorage.removeItem( key ); + }, + flush: function() + { + try { + window.sessionStorage.clear(); + } catch(e) { + // older (3.x) FF does not allow this on sessionStorage + for (var r = 0; r < window.sessionStorage.length; r++) { + window.sessionStorage.removeItem( window.sessionStorage.key(r) ); + } + } } }, @@ -229,10 +272,12 @@ $.store.drivers = { { // Create a non-existing element and append it to the root element (html) this.element = document.createElement( this.nodeName ); - document.documentElement.insertBefore( this.element, document.getElementsByTagName('title')[0] ); + var headElement = document.getElementsByTagName('head')[0]; + headElement.insertBefore( this.element, document.getElementsByTagName('title')[0] ); // Apply userData behavior this.element.addBehavior( "#default#userData" ); this.initialized = true; + return; } catch( e ) { From ef4abceebf69341da39660ed17913b224f0c2195 Mon Sep 17 00:00:00 2001 From: Israel Evans Date: Fri, 27 May 2011 09:56:18 -0700 Subject: [PATCH 3/5] constructor supports choosing driver by scope Signed-off-by: Israel Evans --- jquery.store.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/jquery.store.js b/jquery.store.js index 79da2d4..86b89f3 100644 --- a/jquery.store.js +++ b/jquery.store.js @@ -16,7 +16,7 @@ * $.storage = new $.store(); * // optionally initialize with specific driver and or serializers * $.storage = new $.store( [driver] [, serializers] ); - * driver can be the key (e.g. "windowName") or the driver-object itself + * driver can be a scope ("browser" or "window"), a key (e.g. "windowName") or the driver-object itself * serializers can be a list of named serializers like $.store.serializers ********************************************************************************** * USAGE EXAMPLES: @@ -39,8 +39,20 @@ $.store = function( driver, serializers ) var that = this; if( typeof driver == 'string' ) - { - if( $.store.drivers[ driver ] ) + { + if ( driver == 'browser' ) { + // get the best browser scoped storage + this.driver = $.store.drivers[ 'localStorage' ]; + if( !$.isFunction( this.driver.available ) || !this.driver.available() ) + this.driver = $.store.drivers[ 'userData' ]; + if( !$.isFunction( this.driver.available ) || !this.driver.available() ) + this.driver = $.store.drivers[ 'windowName' ]; //extreme fallback + } else if (driver == 'window' ) { + // get the best browser scoped storage + this.driver = $.store.drivers[ 'sessionStorage' ]; + if( !$.isFunction( this.driver.available ) || !this.driver.available() ) + this.driver = $.store.drivers[ 'windowName' ]; + } else if( $.store.drivers[ driver ] ) this.driver = $.store.drivers[ driver ]; else throw new Error( 'Unknown driver '+ driver ); From ac585967535319dc166d600a64f25b25a9cb83eb Mon Sep 17 00:00:00 2001 From: Israel Evans Date: Fri, 27 May 2011 09:59:01 -0700 Subject: [PATCH 4/5] new methods: length() and key() Signed-off-by: Israel Evans --- jquery.store.js | 69 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/jquery.store.js b/jquery.store.js index 86b89f3..4470f35 100644 --- a/jquery.store.js +++ b/jquery.store.js @@ -25,7 +25,9 @@ * $.storage.set( key, value ); // saves a value * $.storage.del( key ); // deletes a value * $.storage.flush(); // deletes all values - ********************************************************************************** + * $.storage.length(); // the number of key-value pairs in storage + * $.storage.key( index ); // returns a key for the given index (order is not guranteed, so just use it for looping on the set) +********************************************************************************** */ (function($,undefined){ @@ -130,6 +132,14 @@ $.extend( $.store.prototype, { { this.driver.flush(); }, + length: function() + { + return this.driver.length(); + }, + key: function( index ) + { + return this.driver.key( index ); + }, driver : undefined, encoders : [], decoders : [], @@ -209,6 +219,15 @@ $.store.drivers = { flush: function() { window.localStorage.clear(); + }, + length: function() + { + return window.localStorage.length + }, + key: function( index ) + { + return (index >= 0 && index < window.localStorage.length) ? + window.localStorage.key(index) : null; } }, @@ -252,6 +271,15 @@ $.store.drivers = { window.sessionStorage.removeItem( window.sessionStorage.key(r) ); } } + }, + length: function() + { + return window.sessionStorage.length + }, + key: function( index ) + { + return (index >= 0 && index < window.sessionStorage.length) ? + window.sessionStorage.key(index) : null; } }, @@ -263,6 +291,7 @@ $.store.drivers = { nodeName: 'userdatadriver', scope: 'browser', initialized: false, + keys: [], available: function() { try @@ -305,18 +334,38 @@ $.store.drivers = { { this.element.setAttribute( key, value ); this.element.save( this.nodeName ); + this.keys[ this.keys.length ] = key; }, del: function( key ) { this.element.removeAttribute( key ); this.element.save( this.nodeName ); - + var i = this.keys.indexOf( key ); + if (i != -1) this.keys.splice(i, 1); }, flush: function() { // flush by expiration this.element.expires = (new Date).toUTCString(); this.element.save( this.nodeName ); + this.keys = []; + }, + length: function() + { + return this.keys.length + }, + key: function( index ) + { + if (index >= 0 && index < this.keys.length) { + var i = 0; + for (var arrayIndex in this.keys) { + if (index == i++) + return arrayIndex; + } + return null; + } else { + return null; + } } }, @@ -377,6 +426,22 @@ $.store.drivers = { flush: function() { window.name = "{}"; + }, + length: function() + { + return this.cache.length + }, + key: function( index ) + { + if (index >= 0 && index < this.cache.length) { + var i = 0; + for (var arrayIndex in this.cache) { + if (index == i++) return arrayIndex; + } + return null; + } else { + return null; + } } } }; From 3c93cd60c164df7d1e3a602d6dfde316218d79e4 Mon Sep 17 00:00:00 2001 From: Israel Evans Date: Fri, 27 May 2011 10:01:22 -0700 Subject: [PATCH 5/5] updated documentation Signed-off-by: Israel Evans --- README.md | 85 ++++++++++++++++++++++++++++++++++++++++++++---------- index.html | 54 +++++++++++++++++----------------- 2 files changed, 96 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 5647cb2..a69ab4a 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,83 @@ # $.store jQuery plugin # -$.store is a simple, yet easily extensible, plugin to persistently store data on the client side of things. It uses window.localStore where available. Older Internet Explorers will use userData. If all fails $.store will save your data to window.name. +'$.store' is a simple, yet easily extensible, plugin to persistently store data on the client side of things. It uses 'window.localStore' where available. Older Internet Explorers will use 'userData'. If all fails '$.store' will save your data to 'window.name'. -*Note*: The windowName will only do JSON serialization. windowName is not persistent in the sense of making it accross a closed browser window. If you need that ability you should check $.storage.driver.scope == "browser". +*Note*: The 'windowName' driver will only do JSON serialization. 'windowName' is not persistent in the sense of making it across a closed browser window. If you need that ability you should check '$.storage.driver.scope == "browser"'. ## Usage ## -

-//initialize
-$.storage = new $.store();
+	//initialize
+	$.storage = new $.store();
+	
+	// save a value
+	$.storage.set( key, value );
+	
+	// read a value
+	$.storage.get( key );
+	
+	// deletes a value
+	$.storage.del( key );
+	
+	// delete all values
+	$.storage.flush();
 
-// save a value
-$.storage.set( key, value );
+	// get the number of stored entries
+	$.storage.length();
+    
+	// get a key by index (order is not guaranteed, use for iterating through keys)
+	$.storage.key( index );    
+    
+## Adding Serializers ##
 
-// read a value
-$.storage.get( key );
+You can easily add your own serializers to the stack. Make sure to add them before initializing the '$.store'.
 
-// deletes a value
-$.storage.del( key );
+*Note:* Serializers do not apply to the 'windowName' storage driver.
 
-// delete all values
-$.storage.flush();
-
+ $.store.serializers.yaddayadda = { + ident: "$.store.serializers.yaddayadda", + init: function( encoders, decoders ) + { + // register your serializer with en/decoder stack + encoders.unshift( "yaddayadda" ); + decoders.push( "yaddayadda" ); + }, + + isYaddaYadda: function( value ) + { + // determine if value should be processed by this serializer + return true; + }, + + encode: function( value ) + { + // check if the value can be encoded + if( !value || value._serialized || !this.isYaddaYadda( value ) ) + return value; + + // prepare serialized-data-wrapper + var _value = { _serialized: this.ident, value: value }; + + // work your magic + _value.value = "serializedVersionOf data"; + + return value; + }, + + decode: function( value ) + { + // check if the value can be decoded + if( !value || !value._serialized || value._serialized != this.ident ) + return value; + + // work your magic + value.value = "unserializedVersionOf data"; + + return this.isYaddaYadda( value.value ) ? value.value : undefined; + } + }; ## License ## -$.store is published under the [MIT license](http://www.opensource.org/licenses/mit-license.php). \ No newline at end of file +'$.store' is published under the [MIT license][]. + +[MIT license]: http://www.opensource.org/licenses/mit-license.php \ No newline at end of file diff --git a/index.html b/index.html index d11b903..713206b 100644 --- a/index.html +++ b/index.html @@ -60,23 +60,17 @@ document.write( '

Initialized $.storage with driver ' + $.storage.driver.ident + '

' ); -

$.store

- -

- $.store is a simple, yet easily extensible, plugin to persistently store data on the client side of things. - It uses window.localStore where available. Older Internet Explorers will use userData. - If all fails $.store will save your data to window.name. -

- -

- Note: The windowName will only do JSON serialization. windowName - is not persistent in the sense of making it accross a closed browser window. If you need - that ability you should check $.storage.driver.scope == "browser". -

- -

Usage

- -
//initialize
+

$.store jQuery plugin

+ +

$.store is a simple, yet easily extensible, plugin to persistently store data on the client side of things. It uses window.localStore where available. Older Internet Explorers will use userData. If all fails $.store will save your data to window.name.

+ +

The optional cookie driver requires the $.cookie plugin.

+ +

Note: The windowName driver will only do JSON serialization. windowName is not persistent in the sense of making it across a closed browser window. If you need that ability you should check $.storage.driver.scope == "browser".

+ +

Usage

+ +
//initialize
 $.storage = new $.store();
 
 // save a value
@@ -89,16 +83,16 @@ 

Usage

$.storage.del( key ); // delete all values -$.storage.flush();
- -

Adding Serializers

- -

- You can easily add your own serializers to the stack. - Make sure to add them before initializing the $.store. - Note: Serializers do not apply to the windowName storage driver. -

-
$.store.serializers.yaddayadda = {
+$.storage.flush();
+
+ +

Adding Serializers

+ +

You can easily add your own serializers to the stack. Make sure to add them before initializing the $.store.

+ +

Note: Serializers do not apply to the windowName storage driver.

+ +
$.store.serializers.yaddayadda = {
   ident: "$.store.serializers.yaddayadda",
   init: function( encoders, decoders )
   {
@@ -139,8 +133,12 @@ 

Adding Serializers

return this.isYaddaYadda( value.value ) ? value.value : undefined; } -};
+}; +
+ +

License

+

$.store is published under the MIT license.

\ No newline at end of file