1 | dojo.provide("dojox.storage.manager"); |
---|
2 | //dojo.require("dojo.AdapterRegistry"); |
---|
3 | // FIXME: refactor this to use an AdapterRegistry |
---|
4 | |
---|
5 | dojox.storage.manager = new function(){ |
---|
6 | // summary: |
---|
7 | // A singleton class in charge of the dojox.storage system |
---|
8 | // description: |
---|
9 | // Initializes the storage systems and figures out the best available |
---|
10 | // storage options on this platform. |
---|
11 | |
---|
12 | // currentProvider: Object |
---|
13 | // The storage provider that was automagically chosen to do storage |
---|
14 | // on this platform, such as dojox.storage.FlashStorageProvider. |
---|
15 | this.currentProvider = null; |
---|
16 | |
---|
17 | // available: Boolean |
---|
18 | // Whether storage of some kind is available. |
---|
19 | this.available = false; |
---|
20 | |
---|
21 | // providers: Array |
---|
22 | // Array of all the static provider instances, useful if you want to |
---|
23 | // loop through and see what providers have been registered. |
---|
24 | this.providers = []; |
---|
25 | |
---|
26 | this._initialized = false; |
---|
27 | |
---|
28 | this._onLoadListeners = []; |
---|
29 | |
---|
30 | this.initialize = function(){ |
---|
31 | // summary: |
---|
32 | // Initializes the storage system and autodetects the best storage |
---|
33 | // provider we can provide on this platform |
---|
34 | this.autodetect(); |
---|
35 | }; |
---|
36 | |
---|
37 | this.register = function(/*string*/ name, /*Object*/ instance){ |
---|
38 | // summary: |
---|
39 | // Registers the existence of a new storage provider; used by |
---|
40 | // subclasses to inform the manager of their existence. The |
---|
41 | // storage manager will select storage providers based on |
---|
42 | // their ordering, so the order in which you call this method |
---|
43 | // matters. |
---|
44 | // name: |
---|
45 | // The full class name of this provider, such as |
---|
46 | // "dojox.storage.FlashStorageProvider". |
---|
47 | // instance: |
---|
48 | // An instance of this provider, which we will use to call |
---|
49 | // isAvailable() on. |
---|
50 | |
---|
51 | // keep list of providers as a list so that we can know what order |
---|
52 | // storage providers are preferred; also, store the providers hashed |
---|
53 | // by name in case someone wants to get a provider that uses |
---|
54 | // a particular storage backend |
---|
55 | this.providers.push(instance); |
---|
56 | this.providers[name] = instance; |
---|
57 | }; |
---|
58 | |
---|
59 | this.setProvider = function(storageClass){ |
---|
60 | // summary: |
---|
61 | // Instructs the storageManager to use the given storage class for |
---|
62 | // all storage requests. |
---|
63 | // example: |
---|
64 | // | dojox.storage.setProvider( |
---|
65 | // | dojox.storage.IEStorageProvider) |
---|
66 | |
---|
67 | }; |
---|
68 | |
---|
69 | this.autodetect = function(){ |
---|
70 | // summary: |
---|
71 | // Autodetects the best possible persistent storage provider |
---|
72 | // available on this platform. |
---|
73 | |
---|
74 | //console.debug("dojox.storage.manager.autodetect"); |
---|
75 | |
---|
76 | if(this._initialized){ // already finished |
---|
77 | return; |
---|
78 | } |
---|
79 | |
---|
80 | // a flag to force the storage manager to use a particular |
---|
81 | // storage provider type, such as |
---|
82 | // djConfig = {forceStorageProvider: "dojox.storage.WhatWGStorageProvider"}; |
---|
83 | var forceProvider = dojo.config["forceStorageProvider"] || false; |
---|
84 | |
---|
85 | // go through each provider, seeing if it can be used |
---|
86 | var providerToUse; |
---|
87 | //FIXME: use dojo.some |
---|
88 | for(var i = 0; i < this.providers.length; i++){ |
---|
89 | providerToUse = this.providers[i]; |
---|
90 | if(forceProvider && forceProvider == providerToUse.declaredClass){ |
---|
91 | // still call isAvailable for this provider, since this helps some |
---|
92 | // providers internally figure out if they are available |
---|
93 | // FIXME: This should be refactored since it is non-intuitive |
---|
94 | // that isAvailable() would initialize some state |
---|
95 | providerToUse.isAvailable(); |
---|
96 | break; |
---|
97 | }else if(!forceProvider && providerToUse.isAvailable()){ |
---|
98 | break; |
---|
99 | } |
---|
100 | } |
---|
101 | |
---|
102 | if(!providerToUse){ // no provider available |
---|
103 | this._initialized = true; |
---|
104 | this.available = false; |
---|
105 | this.currentProvider = null; |
---|
106 | console.warn("No storage provider found for this platform"); |
---|
107 | this.loaded(); |
---|
108 | return; |
---|
109 | } |
---|
110 | |
---|
111 | // create this provider and mix in it's properties |
---|
112 | // so that developers can do dojox.storage.put rather |
---|
113 | // than dojox.storage.currentProvider.put, for example |
---|
114 | this.currentProvider = providerToUse; |
---|
115 | dojo.mixin(dojox.storage, this.currentProvider); |
---|
116 | |
---|
117 | // have the provider initialize itself |
---|
118 | dojox.storage.initialize(); |
---|
119 | |
---|
120 | this._initialized = true; |
---|
121 | this.available = true; |
---|
122 | }; |
---|
123 | |
---|
124 | this.isAvailable = function(){ /*Boolean*/ |
---|
125 | // summary: |
---|
126 | // Returns whether any storage options are available. |
---|
127 | return this.available; |
---|
128 | }; |
---|
129 | |
---|
130 | this.addOnLoad = function(func){ /* void */ |
---|
131 | // summary: |
---|
132 | // Adds an onload listener to know when Dojo Offline can be used. |
---|
133 | // description: |
---|
134 | // Adds a listener to know when Dojo Offline can be used. This |
---|
135 | // ensures that the Dojo Offline framework is loaded and that the |
---|
136 | // local dojox.storage system is ready to be used. This method is |
---|
137 | // useful if you don't want to have a dependency on Dojo Events |
---|
138 | // when using dojox.storage. |
---|
139 | // func: Function |
---|
140 | // A function to call when Dojo Offline is ready to go |
---|
141 | this._onLoadListeners.push(func); |
---|
142 | |
---|
143 | if(this.isInitialized()){ |
---|
144 | this._fireLoaded(); |
---|
145 | } |
---|
146 | }; |
---|
147 | |
---|
148 | this.removeOnLoad = function(func){ /* void */ |
---|
149 | // summary: |
---|
150 | // Removes the given onLoad listener |
---|
151 | for(var i = 0; i < this._onLoadListeners.length; i++){ |
---|
152 | if(func == this._onLoadListeners[i]){ |
---|
153 | this._onLoadListeners.splice(i, 1); |
---|
154 | break; |
---|
155 | } |
---|
156 | } |
---|
157 | }; |
---|
158 | |
---|
159 | this.isInitialized = function(){ /*Boolean*/ |
---|
160 | // summary: |
---|
161 | // Returns whether the storage system is initialized and ready to |
---|
162 | // be used. |
---|
163 | |
---|
164 | // FIXME: This should REALLY not be in here, but it fixes a tricky |
---|
165 | // Flash timing bug. |
---|
166 | // Confirm that this is still needed with the newly refactored Dojo |
---|
167 | // Flash. Used to be for Internet Explorer. -- Brad Neuberg |
---|
168 | if(this.currentProvider != null |
---|
169 | && this.currentProvider.declaredClass == "dojox.storage.FlashStorageProvider" |
---|
170 | && dojox.flash.ready == false){ |
---|
171 | return false; |
---|
172 | }else{ |
---|
173 | return this._initialized; |
---|
174 | } |
---|
175 | }; |
---|
176 | |
---|
177 | this.supportsProvider = function(/*string*/ storageClass){ /* Boolean */ |
---|
178 | // summary: |
---|
179 | // Determines if this platform supports the given storage provider. |
---|
180 | // example: |
---|
181 | // | dojox.storage.manager.supportsProvider( |
---|
182 | // | "dojox.storage.InternetExplorerStorageProvider"); |
---|
183 | |
---|
184 | // construct this class dynamically |
---|
185 | try{ |
---|
186 | // dynamically call the given providers class level isAvailable() |
---|
187 | // method |
---|
188 | var provider = eval("new " + storageClass + "()"); |
---|
189 | var results = provider.isAvailable(); |
---|
190 | if(!results){ return false; } |
---|
191 | return results; |
---|
192 | }catch(e){ |
---|
193 | return false; |
---|
194 | } |
---|
195 | }; |
---|
196 | |
---|
197 | this.getProvider = function(){ /* Object */ |
---|
198 | // summary: |
---|
199 | // Gets the current provider |
---|
200 | return this.currentProvider; |
---|
201 | }; |
---|
202 | |
---|
203 | this.loaded = function(){ |
---|
204 | // summary: |
---|
205 | // The storage provider should call this method when it is loaded |
---|
206 | // and ready to be used. Clients who will use the provider will |
---|
207 | // connect to this method to know when they can use the storage |
---|
208 | // system. You can either use dojo.connect to connect to this |
---|
209 | // function, or can use dojox.storage.manager.addOnLoad() to add |
---|
210 | // a listener that does not depend on the dojo.event package. |
---|
211 | // example: |
---|
212 | // | if(dojox.storage.manager.isInitialized() == false){ |
---|
213 | // | dojo.connect(dojox.storage.manager, "loaded", TestStorage, "initialize"); |
---|
214 | // | }else{ |
---|
215 | // | dojo.connect(dojo, "loaded", TestStorage, "initialize"); |
---|
216 | // | } |
---|
217 | // example: |
---|
218 | // | dojox.storage.manager.addOnLoad(someFunction); |
---|
219 | |
---|
220 | |
---|
221 | // FIXME: we should just provide a Deferred for this. That way you |
---|
222 | // don't care when this happens or has happened. Deferreds are in Base |
---|
223 | this._fireLoaded(); |
---|
224 | }; |
---|
225 | |
---|
226 | this._fireLoaded = function(){ |
---|
227 | //console.debug("dojox.storage.manager._fireLoaded"); |
---|
228 | |
---|
229 | dojo.forEach(this._onLoadListeners, function(i){ |
---|
230 | try{ |
---|
231 | i(); |
---|
232 | }catch(e){ console.debug(e); } |
---|
233 | }); |
---|
234 | }; |
---|
235 | |
---|
236 | this.getResourceList = function(){ |
---|
237 | // summary: |
---|
238 | // Returns a list of whatever resources are necessary for storage |
---|
239 | // providers to work. |
---|
240 | // description: |
---|
241 | // This will return all files needed by all storage providers for |
---|
242 | // this particular environment type. For example, if we are in the |
---|
243 | // browser environment, then this will return the hidden SWF files |
---|
244 | // needed by the FlashStorageProvider, even if we don't need them |
---|
245 | // for the particular browser we are working within. This is meant |
---|
246 | // to faciliate Dojo Offline, which must retrieve all resources we |
---|
247 | // need offline into the offline cache -- we retrieve everything |
---|
248 | // needed, in case another browser that requires different storage |
---|
249 | // mechanisms hits the local offline cache. For example, if we |
---|
250 | // were to sync against Dojo Offline on Firefox 2, then we would |
---|
251 | // not grab the FlashStorageProvider resources needed for Safari. |
---|
252 | var results = []; |
---|
253 | dojo.forEach(dojox.storage.manager.providers, function(currentProvider){ |
---|
254 | results = results.concat(currentProvider.getResourceList()); |
---|
255 | }); |
---|
256 | |
---|
257 | return results; |
---|
258 | } |
---|
259 | }; |
---|