Subversion Repositories Applications.papyrus

Rev

Blame | Last modification | View Log | RSS feed

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(djConfig["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());

}