279 lines
8 KiB
JavaScript
279 lines
8 KiB
JavaScript
|
if(!dojo._hasResource["dojox.storage.WhatWGStorageProvider"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||
|
dojo._hasResource["dojox.storage.WhatWGStorageProvider"] = true;
|
||
|
dojo.provide("dojox.storage.WhatWGStorageProvider");
|
||
|
dojo.require("dojox.storage.Provider");
|
||
|
dojo.require("dojox.storage.manager");
|
||
|
|
||
|
dojo.declare("dojox.storage.WhatWGStorageProvider", [ dojox.storage.Provider ], {
|
||
|
// summary:
|
||
|
// Storage provider that uses WHAT Working Group features in Firefox 2
|
||
|
// to achieve permanent storage.
|
||
|
// description:
|
||
|
// The WHAT WG storage API is documented at
|
||
|
// http://www.whatwg.org/specs/web-apps/current-work/#scs-client-side
|
||
|
//
|
||
|
// You can disable this storage provider with the following djConfig
|
||
|
// variable:
|
||
|
// var djConfig = { disableWhatWGStorage: true };
|
||
|
//
|
||
|
// Authors of this storage provider-
|
||
|
// JB Boisseau, jb.boisseau@eutech-ssii.com
|
||
|
// Brad Neuberg, bkn3@columbia.edu
|
||
|
|
||
|
initialized: false,
|
||
|
|
||
|
_domain: null,
|
||
|
_available: null,
|
||
|
_statusHandler: null,
|
||
|
_allNamespaces: null,
|
||
|
_storageEventListener: null,
|
||
|
|
||
|
initialize: function(){
|
||
|
if(dojo.config["disableWhatWGStorage"] == true){
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// get current domain
|
||
|
// see: https://bugzilla.mozilla.org/show_bug.cgi?id=357323
|
||
|
this._domain = (location.hostname == "localhost") ? "localhost.localdomain" : location.hostname;
|
||
|
// console.debug(this._domain);
|
||
|
|
||
|
// indicate that this storage provider is now loaded
|
||
|
this.initialized = true;
|
||
|
dojox.storage.manager.loaded();
|
||
|
},
|
||
|
|
||
|
isAvailable: function(){
|
||
|
try{
|
||
|
// see: https://bugzilla.mozilla.org/show_bug.cgi?id=357323
|
||
|
var myStorage = globalStorage[((location.hostname == "localhost") ? "localhost.localdomain" : location.hostname)];
|
||
|
}catch(e){
|
||
|
this._available = false;
|
||
|
return this._available;
|
||
|
}
|
||
|
|
||
|
this._available = true;
|
||
|
return this._available;
|
||
|
},
|
||
|
|
||
|
put: function(key, value, resultsHandler, namespace){
|
||
|
if(this.isValidKey(key) == false){
|
||
|
throw new Error("Invalid key given: " + key);
|
||
|
}
|
||
|
namespace = namespace||this.DEFAULT_NAMESPACE;
|
||
|
|
||
|
// get our full key name, which is namespace + key
|
||
|
key = this.getFullKey(key, namespace);
|
||
|
|
||
|
this._statusHandler = resultsHandler;
|
||
|
|
||
|
// serialize the value;
|
||
|
// handle strings differently so they have better performance
|
||
|
if(dojo.isString(value)){
|
||
|
value = "string:" + value;
|
||
|
}else{
|
||
|
value = dojo.toJson(value);
|
||
|
}
|
||
|
|
||
|
// register for successful storage events.
|
||
|
var storageListener = dojo.hitch(this, function(evt){
|
||
|
// remove any old storage event listener we might have added
|
||
|
// to the window on old put() requests; Firefox has a bug
|
||
|
// where it can occassionaly go into infinite loops calling
|
||
|
// our storage event listener over and over -- this is a
|
||
|
// workaround
|
||
|
// FIXME: Simplify this into a test case and submit it
|
||
|
// to Firefox
|
||
|
window.removeEventListener("storage", storageListener, false);
|
||
|
|
||
|
// indicate we succeeded
|
||
|
if(resultsHandler){
|
||
|
resultsHandler.call(null, this.SUCCESS, key);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
window.addEventListener("storage", storageListener, false);
|
||
|
|
||
|
// try to store the value
|
||
|
try{
|
||
|
var myStorage = globalStorage[this._domain];
|
||
|
myStorage.setItem(key, value);
|
||
|
}catch(e){
|
||
|
// indicate we failed
|
||
|
this._statusHandler.call(null, this.FAILED, key, e.toString());
|
||
|
}
|
||
|
},
|
||
|
|
||
|
get: function(key, namespace){
|
||
|
if(this.isValidKey(key) == false){
|
||
|
throw new Error("Invalid key given: " + key);
|
||
|
}
|
||
|
namespace = namespace||this.DEFAULT_NAMESPACE;
|
||
|
|
||
|
// get our full key name, which is namespace + key
|
||
|
key = this.getFullKey(key, namespace);
|
||
|
|
||
|
// sometimes, even if a key doesn't exist, Firefox
|
||
|
// will return a blank string instead of a null --
|
||
|
// this _might_ be due to having underscores in the
|
||
|
// keyname, but I am not sure.
|
||
|
|
||
|
// FIXME: Simplify this bug into a testcase and
|
||
|
// submit it to Firefox
|
||
|
var myStorage = globalStorage[this._domain];
|
||
|
var results = myStorage.getItem(key);
|
||
|
|
||
|
if(results == null || results == ""){
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
results = results.value;
|
||
|
|
||
|
// destringify the content back into a
|
||
|
// real JavaScript object;
|
||
|
// handle strings differently so they have better performance
|
||
|
if(dojo.isString(results) && (/^string:/.test(results))){
|
||
|
results = results.substring("string:".length);
|
||
|
}else{
|
||
|
results = dojo.fromJson(results);
|
||
|
}
|
||
|
|
||
|
return results;
|
||
|
},
|
||
|
|
||
|
getNamespaces: function(){
|
||
|
var results = [ this.DEFAULT_NAMESPACE ];
|
||
|
|
||
|
// simply enumerate through our array and save any string
|
||
|
// that starts with __
|
||
|
var found = {};
|
||
|
var myStorage = globalStorage[this._domain];
|
||
|
var tester = /^__([^_]*)_/;
|
||
|
for(var i = 0; i < myStorage.length; i++){
|
||
|
var currentKey = myStorage.key(i);
|
||
|
if(tester.test(currentKey) == true){
|
||
|
var currentNS = currentKey.match(tester)[1];
|
||
|
// have we seen this namespace before?
|
||
|
if(typeof found[currentNS] == "undefined"){
|
||
|
found[currentNS] = true;
|
||
|
results.push(currentNS);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return results;
|
||
|
},
|
||
|
|
||
|
getKeys: function(namespace){
|
||
|
namespace = namespace||this.DEFAULT_NAMESPACE;
|
||
|
|
||
|
if(this.isValidKey(namespace) == false){
|
||
|
throw new Error("Invalid namespace given: " + namespace);
|
||
|
}
|
||
|
|
||
|
// create a regular expression to test the beginning
|
||
|
// of our key names to see if they match our namespace;
|
||
|
// if it is the default namespace then test for the presence
|
||
|
// of no namespace for compatibility with older versions
|
||
|
// of dojox.storage
|
||
|
var namespaceTester;
|
||
|
if(namespace == this.DEFAULT_NAMESPACE){
|
||
|
namespaceTester = new RegExp("^([^_]{2}.*)$");
|
||
|
}else{
|
||
|
namespaceTester = new RegExp("^__" + namespace + "_(.*)$");
|
||
|
}
|
||
|
|
||
|
var myStorage = globalStorage[this._domain];
|
||
|
var keysArray = [];
|
||
|
for(var i = 0; i < myStorage.length; i++){
|
||
|
var currentKey = myStorage.key(i);
|
||
|
if(namespaceTester.test(currentKey) == true){
|
||
|
// strip off the namespace portion
|
||
|
currentKey = currentKey.match(namespaceTester)[1];
|
||
|
keysArray.push(currentKey);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return keysArray;
|
||
|
},
|
||
|
|
||
|
clear: function(namespace){
|
||
|
namespace = namespace||this.DEFAULT_NAMESPACE;
|
||
|
|
||
|
if(this.isValidKey(namespace) == false){
|
||
|
throw new Error("Invalid namespace given: " + namespace);
|
||
|
}
|
||
|
|
||
|
// create a regular expression to test the beginning
|
||
|
// of our key names to see if they match our namespace;
|
||
|
// if it is the default namespace then test for the presence
|
||
|
// of no namespace for compatibility with older versions
|
||
|
// of dojox.storage
|
||
|
var namespaceTester;
|
||
|
if(namespace == this.DEFAULT_NAMESPACE){
|
||
|
namespaceTester = new RegExp("^[^_]{2}");
|
||
|
}else{
|
||
|
namespaceTester = new RegExp("^__" + namespace + "_");
|
||
|
}
|
||
|
|
||
|
var myStorage = globalStorage[this._domain];
|
||
|
var keys = [];
|
||
|
for(var i = 0; i < myStorage.length; i++){
|
||
|
if(namespaceTester.test(myStorage.key(i)) == true){
|
||
|
keys[keys.length] = myStorage.key(i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dojo.forEach(keys, dojo.hitch(myStorage, "removeItem"));
|
||
|
},
|
||
|
|
||
|
remove: function(key, namespace){
|
||
|
// get our full key name, which is namespace + key
|
||
|
key = this.getFullKey(key, namespace);
|
||
|
|
||
|
var myStorage = globalStorage[this._domain];
|
||
|
myStorage.removeItem(key);
|
||
|
},
|
||
|
|
||
|
isPermanent: function(){
|
||
|
return true;
|
||
|
},
|
||
|
|
||
|
getMaximumSize: function(){
|
||
|
return this.SIZE_NO_LIMIT;
|
||
|
},
|
||
|
|
||
|
hasSettingsUI: function(){
|
||
|
return false;
|
||
|
},
|
||
|
|
||
|
showSettingsUI: function(){
|
||
|
throw new Error(this.declaredClass + " does not support a storage settings user-interface");
|
||
|
},
|
||
|
|
||
|
hideSettingsUI: function(){
|
||
|
throw new Error(this.declaredClass + " does not support a storage settings user-interface");
|
||
|
},
|
||
|
|
||
|
getFullKey: function(key, namespace){
|
||
|
namespace = namespace||this.DEFAULT_NAMESPACE;
|
||
|
|
||
|
if(this.isValidKey(namespace) == false){
|
||
|
throw new Error("Invalid namespace given: " + namespace);
|
||
|
}
|
||
|
|
||
|
// don't append a namespace string for the default namespace,
|
||
|
// for compatibility with older versions of dojox.storage
|
||
|
if(namespace == this.DEFAULT_NAMESPACE){
|
||
|
return key;
|
||
|
}else{
|
||
|
return "__" + namespace + "_" + key;
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
dojox.storage.manager.register("dojox.storage.WhatWGStorageProvider",
|
||
|
new dojox.storage.WhatWGStorageProvider());
|
||
|
|
||
|
}
|