blob: 83896aea99bd0e699c7901ca37c4846cc9072407 [file] [log] [blame]
/*
Copyright (c) 2004-2006, The Dojo Foundation
All Rights Reserved.
Licensed under the Academic Free License version 2.1 or above OR the
modified BSD license. For more information on Dojo licensing, see:
http://dojotoolkit.org/community/licensing.shtml
*/
dojo.provide("dojo.storage");
dojo.require("dojo.lang.*");
dojo.require("dojo.event.*");
dojo.storage = new function(){
// summary: A singleton for working with Dojo Storage.
// description:
// dojo.storage exposes the current available storage
// provider on this platform. It gives you methods such
// as dojo.storage.put(), dojo.storage.get(), etc.
//
// For more details on Dojo Storage, see the primary
// documentation page at
// http://manual.dojotoolkit.org/storage.html
//
// Note for storage provider developers who are creating
// subclasses-
// This is the base class for all storage providers
// Specific kinds of Storage Providers should subclass this
// and implement these methods. You should avoid initialization
// storage provider subclass's constructor; instead, perform
// initialization in your initialize() method.
}
dojo.declare("dojo.storage", null, {
// SUCCESS: String
// Flag that indicates a put() call to a
// storage provider was succesful.
SUCCESS: "success",
// FAILED: String
// Flag that indicates a put() call to
// a storage provider failed.
FAILED: "failed",
// PENDING: String
// Flag that indicates a put() call to a
// storage provider is pending user approval.
PENDING: "pending",
// SIZE_NOT_AVAILABLE: String
// Returned by getMaximumSize() if this storage provider can not determine
// the maximum amount of data it can support.
SIZE_NOT_AVAILABLE: "Size not available",
// SIZE_NO_LIMIT: String
// Returned by getMaximumSize() if this storage provider has no theoretical
// limit on the amount of data it can store.
SIZE_NO_LIMIT: "No size limit",
// namespace: String
// The namespace for all storage operations. This is useful if several
// applications want access to the storage system from the same domain but
//want different storage silos.
namespace: "default",
// onHideSettingsUI: Function
// If a function is assigned to this property, then when the settings
// provider's UI is closed this function is called. Useful, for example,
// if the user has just cleared out all storage for this provider using
// the settings UI, and you want to update your UI.
onHideSettingsUI: null,
initialize: function(){
// summary:
// Allows this storage provider to initialize itself. This is
// called after the page has finished loading, so you can not do
// document.writes(). Storage Provider subclasses should initialize
// themselves inside of here rather than in their function
// constructor.
dojo.unimplemented("dojo.storage.initialize");
},
isAvailable: function(){ /*Boolean*/
// summary:
// Returns whether this storage provider is available on this
// platform.
dojo.unimplemented("dojo.storage.isAvailable");
},
put: function( /*string*/ key,
/*object*/ value,
/*function*/ resultsHandler){
// summary:
// Puts a key and value into this storage system.
// description:
// Example-
// var resultsHandler = function(status, key, message){
// alert("status="+status+", key="+key+", message="+message);
// };
// dojo.storage.put("test", "hello world", resultsHandler);
// key:
// A string key to use when retrieving this value in the future.
// value:
// A value to store; this can be any JavaScript type.
// resultsHandler:
// A callback function that will receive three arguments. The
// first argument is one of three values: dojo.storage.SUCCESS,
// dojo.storage.FAILED, or dojo.storage.PENDING; these values
// determine how the put request went. In some storage systems
// users can deny a storage request, resulting in a
// dojo.storage.FAILED, while in other storage systems a storage
// request must wait for user approval, resulting in a
// dojo.storage.PENDING status until the request is either
// approved or denied, resulting in another call back with
// dojo.storage.SUCCESS.
// The second argument in the call back is the key name that was being stored.
// The third argument in the call back is an optional message that
// details possible error messages that might have occurred during
// the storage process.
dojo.unimplemented("dojo.storage.put");
},
get: function(/*string*/ key){ /*Object*/
// summary:
// Gets the value with the given key. Returns null if this key is
// not in the storage system.
// key:
// A string key to get the value of.
// return: Returns any JavaScript object type; null if the key is not present
dojo.unimplemented("dojo.storage.get");
},
hasKey: function(/*string*/ key){ /*Boolean*/
// summary: Determines whether the storage has the given key.
return (this.get(key) != null);
},
getKeys: function(){ /*Array*/
// summary: Enumerates all of the available keys in this storage system.
// return: Array of available keys
dojo.unimplemented("dojo.storage.getKeys");
},
clear: function(){
// summary:
// Completely clears this storage system of all of it's values and
// keys.
dojo.unimplemented("dojo.storage.clear");
},
remove: function(key){
// summary: Removes the given key from this storage system.
dojo.unimplemented("dojo.storage.remove");
},
isPermanent: function(){ /*Boolean*/
// summary:
// Returns whether this storage provider's values are persisted
// when this platform is shutdown.
dojo.unimplemented("dojo.storage.isPermanent");
},
getMaximumSize: function(){ /* mixed */
// summary: The maximum storage allowed by this provider
// returns:
// Returns the maximum storage size
// supported by this provider, in
// thousands of bytes (i.e., if it
// returns 60 then this means that 60K
// of storage is supported).
//
// If this provider can not determine
// it's maximum size, then
// dojo.storage.SIZE_NOT_AVAILABLE is
// returned; if there is no theoretical
// limit on the amount of storage
// this provider can return, then
// dojo.storage.SIZE_NO_LIMIT is
// returned
dojo.unimplemented("dojo.storage.getMaximumSize");
},
hasSettingsUI: function(){ /*Boolean*/
// summary: Determines whether this provider has a settings UI.
return false;
},
showSettingsUI: function(){
// summary: If this provider has a settings UI, determined
// by calling hasSettingsUI(), it is shown.
dojo.unimplemented("dojo.storage.showSettingsUI");
},
hideSettingsUI: function(){
// summary: If this provider has a settings UI, hides it.
dojo.unimplemented("dojo.storage.hideSettingsUI");
},
getType: function(){ /*String*/
// summary:
// The provider name as a string, such as
// "dojo.storage.FlashStorageProvider".
dojo.unimplemented("dojo.storage.getType");
},
isValidKey: function(/*string*/ keyName){ /*Boolean*/
// summary:
// Subclasses can call this to ensure that the key given is valid
// in a consistent way across different storage providers. We use
// the lowest common denominator for key values allowed: only
// letters, numbers, and underscores are allowed. No spaces.
if((keyName == null)||(typeof keyName == "undefined")){
return false;
}
return /^[0-9A-Za-z_]*$/.test(keyName);
}
});
dojo.storage.manager = new function(){
// summary: A singleton class in charge of the Dojo Storage system
// description:
// Initializes the storage systems and figures out the best available
// storage options on this platform.
// currentProvider: Object
// The storage provider that was automagically chosen to do storage
// on this platform, such as dojo.storage.browser.FlashStorageProvider.
this.currentProvider = null;
// available: Boolean
// Whether storage of some kind is available
this.available = false;
this._initialized = false;
this._providers = [];
// namespace: String
// An optional namespace value that can be used by a single application
// to partition storage into seperate units - not well supported yet.
this.namespace = "default";
this.initialize = function(){
// summary:
// Initializes the storage system and autodetects the best storage
// provider we can provide on this platform
this.autodetect();
};
this.register = function(/*string*/ name, /*Object*/ instance) {
// summary:
// Registers the existence of a new storage provider; used by
// subclasses to inform the manager of their existence. The
// storage manager will select storage providers based on
// their ordering, so the order in which you call this method
// matters.
// name:
// The full class name of this provider, such as
// "dojo.storage.browser.FlashStorageProvider".
// instance:
// An instance of this provider, which we will use to call
// isAvailable() on.
this._providers[this._providers.length] = instance;
this._providers[name] = instance;
};
this.setProvider = function(storageClass){
// summary:
// Instructs the storageManager to use the given storage class for
// all storage requests.
// description:
// Example-
// dojo.storage.setProvider(
// dojo.storage.browser.IEStorageProvider)
};
this.autodetect = function(){
// summary:
// Autodetects the best possible persistent storage provider
// available on this platform.
if(this._initialized == true){ // already finished
return;
}
// go through each provider, seeing if it can be used
var providerToUse = null;
for(var i = 0; i < this._providers.length; i++){
providerToUse = this._providers[i];
// a flag to force the storage manager to use a particular
// storage provider type, such as
// djConfig = {forceStorageProvider: "dojo.storage.browser.WhatWGStorageProvider"};
if(dojo.lang.isUndefined(djConfig["forceStorageProvider"]) == false
&& providerToUse.getType() == djConfig["forceStorageProvider"]){
// still call isAvailable for this provider, since this helps some
// providers internally figure out if they are available
providerToUse.isAvailable();
break;
}else if(dojo.lang.isUndefined(djConfig["forceStorageProvider"]) == true
&& providerToUse.isAvailable()){
break;
}
}
if(providerToUse == null){ // no provider available
this._initialized = true;
this.available = false;
this.currentProvider = null;
dojo.raise("No storage provider found for this platform");
}
// create this provider and copy over it's properties
this.currentProvider = providerToUse;
for(var i in providerToUse){
dojo.storage[i] = providerToUse[i];
}
dojo.storage.manager = this;
// have the provider initialize itself
dojo.storage.initialize();
this._initialized = true;
this.available = true;
};
this.isAvailable = function(){ /*Boolean*/
// summary: Returns whether any storage options are available.
return this.available;
};
this.isInitialized = function(){ /*Boolean*/
// summary:
// Returns whether the storage system is initialized and ready to
// be used.
// FIXME: This should REALLY not be in here, but it fixes a tricky
// Flash timing bug
if(this.currentProvider.getType() == "dojo.storage.browser.FlashStorageProvider"
&& dojo.flash.ready == false){
return false;
}else{
return this._initialized;
}
};
this.supportsProvider = function(/*string*/ storageClass){ /* Boolean */
// summary: Determines if this platform supports the given storage provider.
// description:
// Example-
// dojo.storage.manager.supportsProvider(
// "dojo.storage.browser.InternetExplorerStorageProvider");
// construct this class dynamically
try{
// dynamically call the given providers class level isAvailable()
// method
var provider = eval("new " + storageClass + "()");
var results = provider.isAvailable();
if(results == null || typeof results == "undefined")
return false;
return results;
}catch (exception){
return false;
}
};
this.getProvider = function(){ /* Object */
// summary: Gets the current provider
return this.currentProvider;
};
this.loaded = function(){
// summary:
// The storage provider should call this method when it is loaded
// and ready to be used. Clients who will use the provider will
// connect to this method to know when they can use the storage
// system.
// description:
// Example-
// if(dojo.storage.manager.isInitialized() == false){
// dojo.event.connect(dojo.storage.manager, "loaded", TestStorage,
// TestStorage.initialize);
// }else{
// dojo.event.connect(dojo, "loaded", TestStorage, TestStorage.initialize);
// }
};
};