summaryrefslogtreecommitdiff
path: root/includes/js/dojox/storage/Storage.as
diff options
context:
space:
mode:
Diffstat (limited to 'includes/js/dojox/storage/Storage.as')
-rw-r--r--includes/js/dojox/storage/Storage.as399
1 files changed, 399 insertions, 0 deletions
diff --git a/includes/js/dojox/storage/Storage.as b/includes/js/dojox/storage/Storage.as
new file mode 100644
index 0000000..8fdd4ed
--- /dev/null
+++ b/includes/js/dojox/storage/Storage.as
@@ -0,0 +1,399 @@
+import DojoExternalInterface;
+
+class Storage{
+ public static var SUCCESS = "success";
+ public static var FAILED = "failed";
+ public static var PENDING = "pending";
+
+ // Wait the following number of milliseconds before flushing
+ public static var FLUSH_DELAY_DEFAULT = 500;
+
+ public var flush_delay;
+ public var so;
+ public var timer;
+
+ private var _NAMESPACE_KEY = "allNamespaces";
+
+ public function Storage(){
+ flush_delay = Storage.FLUSH_DELAY_DEFAULT;
+
+ DojoExternalInterface.initialize();
+ DojoExternalInterface.addCallback("put", this, put);
+ DojoExternalInterface.addCallback("putMultiple", this, putMultiple);
+ DojoExternalInterface.addCallback("get", this, get);
+ DojoExternalInterface.addCallback("getMultiple", this, getMultiple);
+ DojoExternalInterface.addCallback("showSettings", this, showSettings);
+ DojoExternalInterface.addCallback("clear", this, clear);
+ DojoExternalInterface.addCallback("getKeys", this, getKeys);
+ DojoExternalInterface.addCallback("getNamespaces", this, getNamespaces);
+ DojoExternalInterface.addCallback("remove", this, remove);
+ DojoExternalInterface.addCallback("removeMultiple", this, removeMultiple);
+ DojoExternalInterface.addCallback("flush", this, flush);
+ DojoExternalInterface.addCallback("setFlushDelay", this, setFlushDelay);
+ DojoExternalInterface.addCallback("getFlushDelay", this, getFlushDelay);
+ DojoExternalInterface.loaded();
+
+ // preload the System Settings finished button movie for offline
+ // access so it is in the cache
+ _root.createEmptyMovieClip("_settingsBackground", 1);
+ _root._settingsBackground.loadMovie(DojoExternalInterface.dojoPath + "storage_dialog.swf");
+ }
+
+ // FIXME: Whoever added this Flush code did not document why it
+ // exists. Please also put your name and a bug number so I know
+ // who to contact. -- Brad Neuberg
+
+ // Set a new value for the flush delay timer.
+ // Possible values:
+ // 0 : Perform the flush synchronously after each "put" request
+ // > 0 : Wait until 'newDelay' ms have passed without any "put" request to flush
+ // -1 : Do not automatically flush
+ public function setFlushDelay(newDelay){
+ flush_delay = Number(newDelay);
+ }
+
+ public function getFlushDelay(){
+ return String(flush_delay);
+ }
+
+ public function flush(namespace){
+ if(timer){
+ _global.clearTimeout(timer);
+ delete timer;
+ }
+
+ var so = SharedObject.getLocal(namespace);
+ var flushResults = so.flush();
+
+ // return results of this command to JavaScript
+ var statusResults;
+ if(flushResults == true){
+ statusResults = Storage.SUCCESS;
+ }else if(flushResults == "pending"){
+ statusResults = Storage.PENDING;
+ }else{
+ statusResults = Storage.FAILED;
+ }
+
+ DojoExternalInterface.call("dojox.storage._onStatus", statusResults,
+ null, namespace);
+ }
+
+ public function put(keyName, keyValue, namespace){
+ // Get the SharedObject for these values and save it
+ so = SharedObject.getLocal(namespace);
+
+ // Save the key and value
+ so.data[keyName] = keyValue;
+
+ // Save the namespace
+ // FIXME: Tie this into the flush/no-flush stuff below; right now
+ // we immediately write out this namespace. -- Brad Neuberg
+ addNamespace(namespace, keyName);
+
+ // Do all the flush/no-flush stuff
+ var keyNames = new Array();
+ keyNames[0] = keyName;
+ postWrite(so, keyNames, namespace);
+ }
+
+ // FIXME: Whoever added this code did not document what the
+ // put/get multiple functionality is and why it exists. Please
+ // also put your name and a bug number so I know who to contact.
+ // -- Brad Neuberg
+ public function putMultiple(metaKey, metaValue, metaLengths, namespace){
+ // Get the SharedObject for these values and save it
+ so = SharedObject.getLocal(namespace);
+
+ // Create array of keys and value lengths
+ var keys = metaKey.split(",");
+ var lengths = metaLengths.split(",");
+
+ // Loop through the array and write the values
+ for(var i=0;i<keys.length;i++){
+ so.data[keys[i]] = metaValue.slice(0,lengths[i]);
+ metaValue = metaValue.slice(lengths[i]);
+ }
+
+ // Do all the flush/no-flush stuff
+ postWrite(so, keys, namespace);
+ }
+
+ public function postWrite(so, keyNames, namespace){
+ // TODO: Review all this 'handler' stuff. In particular, the flush
+ // could now be with keys pending from several different requests, not
+ // only the ones passed in this method call
+
+ // prepare a storage status handler
+ var self = this;
+ so.onStatus = function(infoObject:Object){
+ //trace("onStatus, infoObject="+infoObject.code);
+
+ // delete the data value if the request was denied
+ if(infoObject.code == "SharedObject.Flush.Failed"){
+ for(var i=0;i<keyNames.length;i++){
+ delete self.so.data[keyNames[i]];
+ }
+ }
+
+ var statusResults;
+ if(infoObject.code == "SharedObject.Flush.Failed"){
+ statusResults = Storage.FAILED;
+ }else if(infoObject.code == "SharedObject.Flush.Pending"){
+ statusResults = Storage.PENDING;
+ }else if(infoObject.code == "SharedObject.Flush.Success"){
+ // if we have succeeded saving our value, see if we
+ // need to update our list of namespaces
+ if(self.hasNamespace(namespace) == true){
+ statusResults = Storage.SUCCESS;
+ }else{
+ // we have a new namespace we must store
+ self.addNamespace(namespace, keyNames[0]);
+ return;
+ }
+ }
+ //trace("onStatus, statusResults="+statusResults);
+
+ // give the status results to JavaScript
+ DojoExternalInterface.call("dojox.storage._onStatus", statusResults,
+ keyNames[0], namespace);
+ }
+
+ // Clear any pending flush timers
+ if(timer){
+ _global.clearTimeout(timer);
+ }
+
+ // If we have a flush delay set, set a timer for its execution
+ if(flush_delay > 0){
+ timer = _global.setTimeout(flush, flush_delay, namespace);
+ // With a flush_delay value of 0, execute the flush request synchronously
+ }else if(flush_delay == 0){
+ flush(namespace);
+ }
+ // Otherwise just don't flush - will be probably be flushed manually
+ }
+
+ public function get(keyName, namespace){
+ // Get the SharedObject for these values and save it
+ so = SharedObject.getLocal(namespace);
+ var results = so.data[keyName];
+
+ return results;
+ }
+
+ // Returns an array with the contents of each key value on the metaKeys array
+ public function getMultiple(metaKeys, namespace){
+ // get the storage object
+ so = SharedObject.getLocal(namespace);
+
+ // Create array of keys to read
+ var keys = metaKeys.split(",");
+ var results = new Array();
+
+ // Read from storage into results array
+ for(var i = 0;i < keys.length;i++){
+ var val = so.data[keys[i]];
+ val = val.split("\\").join("\\\\");
+ val = val.split('"').join('\\"');
+ results.push( val);
+ }
+
+ // Make the results array into a string
+ var metaResults = '["' + results.join('","') + '"]';
+
+ return metaResults;
+ }
+
+ public function showSettings(){
+ // Show the configuration options for the Flash player, opened to the
+ // section for local storage controls (pane 1)
+ System.showSettings(1);
+
+ // there is no way we can intercept when the Close button is pressed, allowing us
+ // to hide the Flash dialog. Instead, we need to load a movie in the
+ // background that we can show a close button on.
+ _root.createEmptyMovieClip("_settingsBackground", 1);
+ _root._settingsBackground.loadMovie(DojoExternalInterface.dojoPath + "storage_dialog.swf");
+ }
+
+ public function clear(namespace){
+ so = SharedObject.getLocal(namespace);
+ so.clear();
+ so.flush();
+
+ // remove this namespace entry now
+ removeNamespace(namespace);
+ }
+
+ public function getKeys(namespace) : String{
+ // Returns a list of the available keys in this namespace
+
+ // get the storage object
+ so = SharedObject.getLocal(namespace);
+ // get all of the keys
+ var results = [];
+ for(var i in so.data){
+ results.push(i);
+ }
+
+ // remove our key that records our list of namespaces
+ for(var i = 0; i < results.length; i++){
+ if(results[i] == _NAMESPACE_KEY){
+ results.splice(i, 1);
+ break;
+ }
+ }
+
+ // a bug in ExternalInterface transforms Arrays into
+ // Strings, so we can't use those here! -- BradNeuberg
+ results = results.join(",");
+
+ return results;
+ }
+
+ public function getNamespaces() : String{
+ var allNamespaces = SharedObject.getLocal(_NAMESPACE_KEY);
+ var results = [];
+
+ for(var i in allNamespaces.data){
+ results.push(i);
+ }
+
+ // a bug in ExternalInterface transforms Arrays into
+ // Strings, so we can use those here! -- BradNeuberg
+ results = results.join(",");
+
+ return results;
+ }
+
+ public function remove(keyName, namespace){
+ // Removes a key
+
+ // get the storage object
+ so = SharedObject.getLocal(namespace);
+
+ // delete this value
+ delete so.data[keyName];
+
+ // save the changes
+ so.flush();
+
+ // see if we are the last entry for this namespace
+ var availableKeys = getKeys(namespace);
+ if(availableKeys == ""){
+ // we are empty
+ removeNamespace(namespace);
+ }
+ }
+
+ // Removes all the values for each keys on the metaKeys array
+ public function removeMultiple(metaKeys, namespace){
+ // get the storage object
+ so = SharedObject.getLocal(namespace);
+
+ // Create array of keys to read
+ var keys = metaKeys.split(",");
+ var results = new Array();
+
+ // Delete elements
+ for(var i=0;i<keys.length;i++){
+ delete so.data[keys[i]];
+ }
+
+ // see if there are no more entries for this namespace
+ var availableKeys = getKeys(namespace);
+ if(availableKeys == ""){
+ // we are empty
+ removeNamespace(namespace);
+ }
+ }
+
+ private function hasNamespace(namespace):Boolean{
+ // Get the SharedObject for the namespace list
+ var allNamespaces = SharedObject.getLocal(_NAMESPACE_KEY);
+
+ var results = false;
+ for(var i in allNamespaces.data){
+ if(i == namespace){
+ results = true;
+ break;
+ }
+ }
+
+ return results;
+ }
+
+ // FIXME: This code has gotten ugly -- refactor
+ private function addNamespace(namespace, keyName){
+ if(hasNamespace(namespace) == true){
+ return;
+ }
+
+ // Get the SharedObject for the namespace list
+ var allNamespaces = SharedObject.getLocal(_NAMESPACE_KEY);
+
+ // prepare a storage status handler if the keyName is
+ // not null
+ if(keyName != null && typeof keyName != "undefined"){
+ var self = this;
+ allNamespaces.onStatus = function(infoObject:Object){
+ // delete the data value if the request was denied
+ if(infoObject.code == "SharedObject.Flush.Failed"){
+ delete self.so.data[keyName];
+ }
+
+ var statusResults;
+ if(infoObject.code == "SharedObject.Flush.Failed"){
+ statusResults = Storage.FAILED;
+ }else if(infoObject.code == "SharedObject.Flush.Pending"){
+ statusResults = Storage.PENDING;
+ }else if(infoObject.code == "SharedObject.Flush.Success"){
+ statusResults = Storage.SUCCESS;
+ }
+
+ // give the status results to JavaScript
+ DojoExternalInterface.call("dojox.storage._onStatus", statusResults,
+ keyName, namespace);
+ }
+ }
+
+ // save the namespace list
+ allNamespaces.data[namespace] = true;
+ var flushResults = allNamespaces.flush();
+
+ // return results of this command to JavaScript
+ if(keyName != null && typeof keyName != "undefined"){
+ var statusResults;
+ if(flushResults == true){
+ statusResults = Storage.SUCCESS;
+ }else if(flushResults == "pending"){
+ statusResults = Storage.PENDING;
+ }else{
+ statusResults = Storage.FAILED;
+ }
+
+ DojoExternalInterface.call("dojox.storage._onStatus", statusResults,
+ keyName, namespace);
+ }
+ }
+
+ // FIXME: This code has gotten ugly -- refactor
+ private function removeNamespace(namespace){
+ if(hasNamespace(namespace) == false){
+ return;
+ }
+
+ // try to save the namespace list; don't have a return
+ // callback; if we fail on this, the worst that will happen
+ // is that we have a spurious namespace entry
+ var allNamespaces = SharedObject.getLocal(_NAMESPACE_KEY);
+ delete allNamespaces.data[namespace];
+ allNamespaces.flush();
+ }
+
+ static function main(mc){
+ _root.app = new Storage();
+ }
+}
+