aboutsummaryrefslogtreecommitdiff
path: root/includes/js/dojox/storage/manager.js
blob: 0198a6dc1611fbcd035e47701c0b4fe707b734bb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
if(!dojo._hasResource["dojox.storage.manager"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.storage.manager"] = true;
dojo.provide("dojox.storage.manager");
//dojo.require("dojo.AdapterRegistry");
// FIXME: refactor this to use an AdapterRegistry

dojox.storage.manager = new function(){
	// summary: A singleton class in charge of the dojox.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 dojox.storage.FlashStorageProvider.
	this.currentProvider = null;
	
	// available: Boolean
	//	Whether storage of some kind is available.
	this.available = false;

  // providers: Array
  //  Array of all the static provider instances, useful if you want to
  //  loop through and see what providers have been registered.
  this.providers = [];
	
	this._initialized = false;

	this._onLoadListeners = [];
	
	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
		//		"dojox.storage.FlashStorageProvider".
		// instance:
		//		An instance of this provider, which we will use to call
		//		isAvailable() on. 
		
		// keep list of providers as a list so that we can know what order
		// storage providers are preferred; also, store the providers hashed
		// by name in case someone wants to get a provider that uses
		// a particular storage backend
		this.providers.push(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-
		//			dojox.storage.setProvider(
		//				dojox.storage.IEStorageProvider)
	
	};
	
	this.autodetect = function(){
		// summary:
		//		Autodetects the best possible persistent storage provider
		//		available on this platform. 
		
		//console.debug("dojox.storage.manager.autodetect");
		
		if(this._initialized){ // already finished
			return;
		}

		// a flag to force the storage manager to use a particular 
		// storage provider type, such as 
		// djConfig = {forceStorageProvider: "dojox.storage.WhatWGStorageProvider"};
		var forceProvider = dojo.config["forceStorageProvider"] || false;

		// go through each provider, seeing if it can be used
		var providerToUse;
		//FIXME: use dojo.some
		for(var i = 0; i < this.providers.length; i++){
			providerToUse = this.providers[i];
			if(forceProvider && forceProvider == providerToUse.declaredClass){
				// still call isAvailable for this provider, since this helps some
				// providers internally figure out if they are available
				// FIXME: This should be refactored since it is non-intuitive
				// that isAvailable() would initialize some state
				providerToUse.isAvailable();
				break;
			}else if(!forceProvider && providerToUse.isAvailable()){
				break;
			}
		}
		
		if(!providerToUse){ // no provider available
			this._initialized = true;
			this.available = false;
			this.currentProvider = null;
			console.warn("No storage provider found for this platform");
			this.loaded();
			return;
		}
			
		// create this provider and mix in it's properties
		// so that developers can do dojox.storage.put rather
		// than dojox.storage.currentProvider.put, for example
		this.currentProvider = providerToUse;
		dojo.mixin(dojox.storage, this.currentProvider);
		
		// have the provider initialize itself
		dojox.storage.initialize();
		
		this._initialized = true;
		this.available = true;
	};
	
	this.isAvailable = function(){ /*Boolean*/
		// summary: Returns whether any storage options are available.
		return this.available;
	};
	
	this.addOnLoad = function(func){ /* void */
		// summary:
		//		Adds an onload listener to know when Dojo Offline can be used.
		// description:
		//		Adds a listener to know when Dojo Offline can be used. This
		//		ensures that the Dojo Offline framework is loaded and that the
		//		local dojox.storage system is ready to be used. This method is
		//		useful if you don't want to have a dependency on Dojo Events
		//		when using dojox.storage.
		// func: Function
		//		A function to call when Dojo Offline is ready to go
		this._onLoadListeners.push(func);
		
		if(this.isInitialized()){
			this._fireLoaded();
		}
	};
	
	this.removeOnLoad = function(func){ /* void */
		// summary: Removes the given onLoad listener
		for(var i = 0; i < this._onLoadListeners.length; i++){
			if(func == this._onLoadListeners[i]){
				this._onLoadListeners = this._onLoadListeners.splice(i, 1);
				break;
			}
		}
	};
	
	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.
		// Confirm that this is still needed with the newly refactored Dojo
		// Flash. Used to be for Internet Explorer. -- Brad Neuberg
		if(this.currentProvider != null
			&& this.currentProvider.declaredClass == "dojox.storage.FlashStorageProvider" 
			&& dojox.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-
		//			dojox.storage.manager.supportsProvider(
		//				"dojox.storage.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){ return false; }
			return results;
		}catch(e){
			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. You can either use dojo.connect to connect to this
		//		function, or can use dojox.storage.manager.addOnLoad() to add
		//		a listener that does not depend on the dojo.event package.
		// description:
		//		Example 1-
		//			if(dojox.storage.manager.isInitialized() == false){ 
		//				dojo.connect(dojox.storage.manager, "loaded", TestStorage, "initialize");
		//			}else{
		//				dojo.connect(dojo, "loaded", TestStorage, "initialize");
		//			}
		//		Example 2-
		//			dojox.storage.manager.addOnLoad(someFunction);


		// FIXME: we should just provide a Deferred for this. That way you
		// don't care when this happens or has happened. Deferreds are in Base
		this._fireLoaded();
	};
	
	this._fireLoaded = function(){
		//console.debug("dojox.storage.manager._fireLoaded");
		
		dojo.forEach(this._onLoadListeners, function(i){ 
			try{ 
				i(); 
			}catch(e){ console.debug(e); } 
		});
	};
	
	this.getResourceList = function(){
		// summary:
		//		Returns a list of whatever resources are necessary for storage
		//		providers to work. 
		// description:
		//		This will return all files needed by all storage providers for
		//		this particular environment type. For example, if we are in the
		//		browser environment, then this will return the hidden SWF files
		//		needed by the FlashStorageProvider, even if we don't need them
		//		for the particular browser we are working within. This is meant
		//		to faciliate Dojo Offline, which must retrieve all resources we
		//		need offline into the offline cache -- we retrieve everything
		//		needed, in case another browser that requires different storage
		//		mechanisms hits the local offline cache. For example, if we
		//		were to sync against Dojo Offline on Firefox 2, then we would
		//		not grab the FlashStorageProvider resources needed for Safari.
		var results = [];
		dojo.forEach(dojox.storage.manager.providers, function(currentProvider){
			results = results.concat(currentProvider.getResourceList());
		});
		
		return results;
	}
};

}