You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
204 lines
5.3 KiB
204 lines
5.3 KiB
define([ |
|
"dojo/_base/declare", |
|
"dojox/storage/Provider", |
|
"dojox/storage/manager", |
|
"dojo/_base/array", |
|
"dojo/_base/lang", |
|
"dojo/json" |
|
], function(declare, Provider, storageManager, array, lang, JSON){ |
|
var LocalStorageProvider = declare("dojox.storage.LocalStorageProvider", [Provider], { |
|
store: null, |
|
initialize: function(){ |
|
|
|
this.store = localStorage; |
|
|
|
this.initialized = true; |
|
storageManager.loaded(); |
|
}, |
|
|
|
isAvailable: function(){ /*Boolean*/ |
|
return typeof localStorage != "undefined"; |
|
}, |
|
|
|
put: function( /*string*/ key, |
|
/*object*/ value, |
|
/*function*/ resultsHandler, |
|
/*string?*/ namespace){ |
|
|
|
// TODO: Use the events as specified in http://dev.w3.org/html5/webstorage/#the-storage-event ? |
|
// Currently, the storage event is not reliable around browsers. |
|
|
|
this._assertIsValidKey(key); |
|
|
|
namespace = namespace||this.DEFAULT_NAMESPACE; |
|
this._assertIsValidNamespace(namespace); |
|
|
|
var fullKey = this.getFullKey(key,namespace); |
|
|
|
// prepending a prefix to a string value |
|
// will result in that prefix not being |
|
// usable as a value, so we better use |
|
// toJson() always. |
|
value = JSON.stringify(value); |
|
|
|
try { // ua may raise an QUOTA_EXCEEDED_ERR exception |
|
this.store.setItem(fullKey,value); |
|
|
|
if(resultsHandler){ |
|
resultsHandler(this.SUCCESS, key, null, namespace); |
|
} |
|
} catch(e) { |
|
if(resultsHandler){ |
|
resultsHandler(this.FAILED, key, e.toString(), namespace); |
|
} |
|
} |
|
}, |
|
|
|
get: function(/*string*/ key, /*string?*/ namespace){ /*Object*/ |
|
this._assertIsValidKey(key); |
|
|
|
namespace = namespace||this.DEFAULT_NAMESPACE; |
|
this._assertIsValidNamespace(namespace); |
|
|
|
// get our full key name, which is namespace + key |
|
key = this.getFullKey(key, namespace); |
|
|
|
return JSON.parse(this.store.getItem(key)); |
|
}, |
|
|
|
getKeys: function(/*string?*/ namespace){ /*Array*/ |
|
namespace = namespace||this.DEFAULT_NAMESPACE; |
|
this._assertIsValidNamespace(namespace); |
|
|
|
namespace = '__'+namespace+'_' |
|
|
|
var keys = []; |
|
for(var i = 0; i < this.store.length; i++){ |
|
var currentKey = this.store.key(i); |
|
if(this._beginsWith(currentKey,namespace)){ |
|
currentKey = currentKey.substring(namespace.length); |
|
keys.push(currentKey); |
|
} |
|
} |
|
|
|
return keys; |
|
}, |
|
|
|
clear: function(/*string?*/ namespace){ |
|
// Um, well, the 'specs' in Provider.js say that if |
|
// no namespace is given, this method should nuke |
|
// the *complete* storage. As other components might |
|
// be using localStorage too, this might not be a |
|
// good idea, so this method won't do it. |
|
|
|
namespace = namespace||this.DEFAULT_NAMESPACE; |
|
this._assertIsValidNamespace(namespace); |
|
|
|
namespace = '__'+namespace+'_'; |
|
|
|
var keys = []; |
|
for(var i = 0; i < this.store.length; i++){ |
|
if(this._beginsWith(this.store.key(i),namespace)){ |
|
keys.push(this.store.key(i)); |
|
} |
|
} |
|
|
|
array.forEach(keys, lang.hitch(this.store, "removeItem")); |
|
}, |
|
|
|
remove: function(/*string*/ key, /*string?*/ namespace){ |
|
namespace = namespace||this.DEFAULT_NAMESPACE; |
|
this._assertIsValidNamespace(namespace); |
|
|
|
this.store.removeItem(this.getFullKey(key, namespace)); |
|
}, |
|
|
|
getNamespaces: function(){ /*string[]*/ |
|
// There must be a better way than |
|
// to execute a regex on *every* |
|
// item in the store. |
|
|
|
var results = [ this.DEFAULT_NAMESPACE]; |
|
|
|
var found = {}; |
|
found[this.DEFAULT_NAMESPACE] = true; |
|
var tester = /^__([^_]*)_/; |
|
|
|
for(var i = 0; i < this.store.length; i++){ |
|
var currentKey = this.store.key(i); |
|
if(tester.test(currentKey) == true){ |
|
var currentNS = currentKey.match(tester)[1]; |
|
if(typeof found[currentNS] == "undefined"){ |
|
found[currentNS] = true; |
|
results.push(currentNS); |
|
} |
|
} |
|
} |
|
|
|
return results; |
|
}, |
|
|
|
isPermanent: function(){ /*Boolean*/ |
|
return true; |
|
}, |
|
|
|
getMaximumSize: function(){ /* mixed */ |
|
return dojox.storage.SIZE_NO_LIMIT; |
|
}, |
|
|
|
hasSettingsUI: function(){ /*Boolean*/ |
|
return false; |
|
}, |
|
|
|
isValidKey: function(/*string*/ keyName){ /*Boolean*/ |
|
if(keyName === null || keyName === undefined){ |
|
return false; |
|
} |
|
|
|
return /^[0-9A-Za-z_-]*$/.test(keyName); |
|
}, |
|
|
|
isValidNamespace: function(/*string*/ keyName){ /*Boolean*/ |
|
// we *must* prevent namespaces from having |
|
// underscores - else lookup of namespaces |
|
// via RegEx (e.g. in getNamespaces ) would |
|
// return wrong results. |
|
// |
|
// The only way around this would be to |
|
// disallow underscores in keys. |
|
|
|
if(keyName === null || keyName === undefined){ |
|
return false; |
|
} |
|
|
|
return /^[0-9A-Za-z-]*$/.test(keyName); |
|
}, |
|
|
|
getFullKey: function(key, namespace){ |
|
// checks for valid namespace and |
|
// key are already performed. |
|
return "__" + namespace + "_" + key; |
|
}, |
|
|
|
_beginsWith: function(/* string */ haystack, /* string */ needle) { |
|
if(needle.length > haystack.length) { |
|
return false; |
|
} |
|
return haystack.substring(0,needle.length) === needle; |
|
}, |
|
|
|
_assertIsValidNamespace: function(/* string */ namespace){ |
|
if(this.isValidNamespace(namespace) === false){ |
|
throw new Error("Invalid namespace given: " + namespace); |
|
} |
|
}, |
|
|
|
_assertIsValidKey: function(/* string */ key){ |
|
if(this.isValidKey(key) === false){ |
|
throw new Error("Invalid key given: " + key); |
|
} |
|
} |
|
}); |
|
storageManager.register("dojox.storage.LocalStorageProvider", new LocalStorageProvider()); |
|
return LocalStorageProvider; |
|
});
|
|
|