1 |
efrain |
1 |
YUI.add('yui2-storage', function(Y) {
|
|
|
2 |
var YAHOO = Y.YUI2;
|
|
|
3 |
/*
|
|
|
4 |
Copyright (c) 2011, Yahoo! Inc. All rights reserved.
|
|
|
5 |
Code licensed under the BSD License:
|
|
|
6 |
http://developer.yahoo.com/yui/license.html
|
|
|
7 |
version: 2.9.0
|
|
|
8 |
*/
|
|
|
9 |
/**
|
|
|
10 |
* The Storage module manages client-side data storage.
|
|
|
11 |
* @module Storage
|
|
|
12 |
*/
|
|
|
13 |
|
|
|
14 |
(function() {
|
|
|
15 |
|
|
|
16 |
// internal shorthand
|
|
|
17 |
var Y = YAHOO,
|
|
|
18 |
Util = Y.util,
|
|
|
19 |
Lang = Y.lang,
|
|
|
20 |
_logOverwriteError,
|
|
|
21 |
Storage,
|
|
|
22 |
|
|
|
23 |
RX_TYPE = /^type=(\w+)/i,
|
|
|
24 |
RX_VALUE = /&value=(.*)/i;
|
|
|
25 |
|
|
|
26 |
if (! Util.Storage) {
|
|
|
27 |
_logOverwriteError = function(fxName) {
|
|
|
28 |
Y.log('Exception in YAHOO.util.Storage.?? - must be extended by a storage engine'.replace('??', fxName).replace('??', this.getName ? this.getName() : 'Unknown'), 'error');
|
|
|
29 |
};
|
|
|
30 |
|
|
|
31 |
/**
|
|
|
32 |
* The Storage class is an HTML 5 storage API clone, used to wrap individual storage implementations with a common API.
|
|
|
33 |
* @class Storage
|
|
|
34 |
* @namespace YAHOO.util
|
|
|
35 |
* @constructor
|
|
|
36 |
* @param sLocation {String} Required. The storage location.
|
|
|
37 |
* @parm sName {String} Required. The engine name.
|
|
|
38 |
* @param oConf {Object} Required. A configuration object.
|
|
|
39 |
*/
|
|
|
40 |
Storage = function(sLocation, sName, oConf) {
|
|
|
41 |
var that = this;
|
|
|
42 |
Y.env._id_counter += 1;
|
|
|
43 |
|
|
|
44 |
// protected variables
|
|
|
45 |
that._cfg = Lang.isObject(oConf) ? oConf : {};
|
|
|
46 |
that._location = sLocation;
|
|
|
47 |
that._name = sName;
|
|
|
48 |
that.isReady = false;
|
|
|
49 |
|
|
|
50 |
// public variables
|
|
|
51 |
that.createEvent(Storage.CE_READY, {scope: that, fireOnce: true});
|
|
|
52 |
that.createEvent(Storage.CE_CHANGE, {scope: that});
|
|
|
53 |
|
|
|
54 |
that.subscribe(Storage.CE_READY, function() {
|
|
|
55 |
that.isReady = true;
|
|
|
56 |
});
|
|
|
57 |
};
|
|
|
58 |
|
|
|
59 |
Storage.CE_READY = 'YUIStorageReady';
|
|
|
60 |
Storage.CE_CHANGE = 'YUIStorageChange';
|
|
|
61 |
|
|
|
62 |
Storage.prototype = {
|
|
|
63 |
|
|
|
64 |
/**
|
|
|
65 |
* The event name for when the storage item is ready.
|
|
|
66 |
* @property CE_READY
|
|
|
67 |
* @type {String}
|
|
|
68 |
* @public
|
|
|
69 |
*/
|
|
|
70 |
CE_READY: Storage.CE_READY,
|
|
|
71 |
|
|
|
72 |
/**
|
|
|
73 |
* The event name for when the storage item has changed.
|
|
|
74 |
* @property CE_CHANGE
|
|
|
75 |
* @type {String}
|
|
|
76 |
* @public
|
|
|
77 |
*/
|
|
|
78 |
CE_CHANGE: Storage.CE_CHANGE,
|
|
|
79 |
|
|
|
80 |
/**
|
|
|
81 |
* The configuration of the engine.
|
|
|
82 |
* @property _cfg
|
|
|
83 |
* @type {Object}
|
|
|
84 |
* @protected
|
|
|
85 |
*/
|
|
|
86 |
_cfg: '',
|
|
|
87 |
|
|
|
88 |
/**
|
|
|
89 |
* The name of this engine.
|
|
|
90 |
* @property _name
|
|
|
91 |
* @type {String}
|
|
|
92 |
* @protected
|
|
|
93 |
*/
|
|
|
94 |
_name: '',
|
|
|
95 |
|
|
|
96 |
/**
|
|
|
97 |
* The location for this instance.
|
|
|
98 |
* @property _location
|
|
|
99 |
* @type {String}
|
|
|
100 |
* @protected
|
|
|
101 |
*/
|
|
|
102 |
_location: '',
|
|
|
103 |
|
|
|
104 |
/**
|
|
|
105 |
* The current length of the keys.
|
|
|
106 |
* @property length
|
|
|
107 |
* @type {Number}
|
|
|
108 |
* @public
|
|
|
109 |
*/
|
|
|
110 |
length: 0,
|
|
|
111 |
|
|
|
112 |
/**
|
|
|
113 |
* This engine singleton has been initialized already.
|
|
|
114 |
* @property isReady
|
|
|
115 |
* @type {String}
|
|
|
116 |
* @protected
|
|
|
117 |
*/
|
|
|
118 |
isReady: false,
|
|
|
119 |
|
|
|
120 |
/**
|
|
|
121 |
* Clears any existing key/value pairs.
|
|
|
122 |
* @method clear
|
|
|
123 |
* @public
|
|
|
124 |
*/
|
|
|
125 |
clear: function() {
|
|
|
126 |
this._clear();
|
|
|
127 |
this.length = 0;
|
|
|
128 |
},
|
|
|
129 |
|
|
|
130 |
/**
|
|
|
131 |
* Fetches the data stored and the provided key.
|
|
|
132 |
* @method getItem
|
|
|
133 |
* @param sKey {String} Required. The key used to reference this value (DOMString in HTML 5 spec).
|
|
|
134 |
* @return {String|NULL} The value stored at the provided key (DOMString in HTML 5 spec).
|
|
|
135 |
* @public
|
|
|
136 |
*/
|
|
|
137 |
getItem: function(sKey) {
|
|
|
138 |
Y.log("Fetching item at " + sKey);
|
|
|
139 |
var oItem = this._getItem(sKey);
|
|
|
140 |
return Lang.isValue(oItem) ? this._getValue(oItem) : null; // required by HTML 5 spec
|
|
|
141 |
},
|
|
|
142 |
|
|
|
143 |
/**
|
|
|
144 |
* Fetches the storage object's name; should be overwritten by storage engine.
|
|
|
145 |
* @method getName
|
|
|
146 |
* @return {String} The name of the data storage object.
|
|
|
147 |
* @public
|
|
|
148 |
*/
|
|
|
149 |
getName: function() {return this._name;},
|
|
|
150 |
|
|
|
151 |
/**
|
|
|
152 |
* Tests if the key has been set (not in HTML 5 spec); should be overwritten by storage engine.
|
|
|
153 |
* @method hasKey
|
|
|
154 |
* @param sKey {String} Required. The key to search for.
|
|
|
155 |
* @return {Boolean} True when key has been set.
|
|
|
156 |
* @public
|
|
|
157 |
*/
|
|
|
158 |
hasKey: function(sKey) {
|
|
|
159 |
return Lang.isString(sKey) && this._hasKey(sKey);
|
|
|
160 |
},
|
|
|
161 |
|
|
|
162 |
/**
|
|
|
163 |
* Retrieve the key stored at the provided index; should be overwritten by storage engine.
|
|
|
164 |
* @method key
|
|
|
165 |
* @param nIndex {Number} Required. The index to retrieve (unsigned long in HTML 5 spec).
|
|
|
166 |
* @return {String} Required. The key at the provided index (DOMString in HTML 5 spec).
|
|
|
167 |
* @public
|
|
|
168 |
*/
|
|
|
169 |
key: function(nIndex) {
|
|
|
170 |
Y.log("Fetching key at " + nIndex);
|
|
|
171 |
|
|
|
172 |
if (Lang.isNumber(nIndex) && -1 < nIndex && this.length > nIndex) {
|
|
|
173 |
var value = this._key(nIndex);
|
|
|
174 |
if (value) {return value;}
|
|
|
175 |
}
|
|
|
176 |
|
|
|
177 |
// this is thrown according to the HTML5 spec
|
|
|
178 |
throw('INDEX_SIZE_ERR - Storage.setItem - The provided index (' + nIndex + ') is not available');
|
|
|
179 |
},
|
|
|
180 |
|
|
|
181 |
/**
|
|
|
182 |
* Remove an item from the data storage.
|
|
|
183 |
* @method removeItem
|
|
|
184 |
* @param sKey {String} Required. The key to remove (DOMString in HTML 5 spec).
|
|
|
185 |
* @public
|
|
|
186 |
*/
|
|
|
187 |
removeItem: function(sKey) {
|
|
|
188 |
Y.log("removing " + sKey);
|
|
|
189 |
var that = this,
|
|
|
190 |
oOldValue;
|
|
|
191 |
|
|
|
192 |
if (that.hasKey(sKey)) {
|
|
|
193 |
oOldValue = that._getItem(sKey);
|
|
|
194 |
if (! oOldValue) {oOldValue = null;}
|
|
|
195 |
that._removeItem(sKey);
|
|
|
196 |
that.fireEvent(Storage.CE_CHANGE, new Util.StorageEvent(that, sKey, oOldValue, null, Util.StorageEvent.TYPE_REMOVE_ITEM));
|
|
|
197 |
}
|
|
|
198 |
else {
|
|
|
199 |
// HTML 5 spec says to do nothing
|
|
|
200 |
}
|
|
|
201 |
},
|
|
|
202 |
|
|
|
203 |
/**
|
|
|
204 |
* Adds an item to the data storage.
|
|
|
205 |
* @method setItem
|
|
|
206 |
* @param sKey {String} Required. The key used to reference this value (DOMString in HTML 5 spec).
|
|
|
207 |
* @param oData {Object} Required. The data to store at key (DOMString in HTML 5 spec).
|
|
|
208 |
* @public
|
|
|
209 |
* @throws QUOTA_EXCEEDED_ERROR
|
|
|
210 |
*/
|
|
|
211 |
setItem: function(sKey, oData) {
|
|
|
212 |
Y.log("SETTING " + oData + " to " + sKey);
|
|
|
213 |
|
|
|
214 |
if (Lang.isString(sKey)) {
|
|
|
215 |
var that = this,
|
|
|
216 |
oOldValue = that._getItem(sKey);
|
|
|
217 |
|
|
|
218 |
if (! oOldValue) {oOldValue = null;}
|
|
|
219 |
|
|
|
220 |
if (that._setItem(sKey, that._createValue(oData))) {
|
|
|
221 |
that.fireEvent(Storage.CE_CHANGE, new Util.StorageEvent(that, sKey, oOldValue, oData,
|
|
|
222 |
that.hasKey(sKey) ? Util.StorageEvent.TYPE_UPDATE_ITEM : Util.StorageEvent.TYPE_ADD_ITEM));
|
|
|
223 |
}
|
|
|
224 |
else {
|
|
|
225 |
// that is thrown according to the HTML5 spec
|
|
|
226 |
throw('QUOTA_EXCEEDED_ERROR - Storage.setItem - The choosen storage method (' +
|
|
|
227 |
that.getName() + ') has exceeded capacity');
|
|
|
228 |
}
|
|
|
229 |
}
|
|
|
230 |
else {
|
|
|
231 |
// HTML 5 spec says to do nothing
|
|
|
232 |
}
|
|
|
233 |
},
|
|
|
234 |
|
|
|
235 |
/**
|
|
|
236 |
* Implementation of the clear login; should be overwritten by storage engine.
|
|
|
237 |
* @method _clear
|
|
|
238 |
* @protected
|
|
|
239 |
*/
|
|
|
240 |
_clear: function() {
|
|
|
241 |
_logOverwriteError('_clear');
|
|
|
242 |
return '';
|
|
|
243 |
},
|
|
|
244 |
|
|
|
245 |
/**
|
|
|
246 |
* Converts the object into a string, with meta data (type), so it can be restored later.
|
|
|
247 |
* @method _createValue
|
|
|
248 |
* @param o {Object} Required. An object to store.
|
|
|
249 |
* @protected
|
|
|
250 |
*/
|
|
|
251 |
_createValue: function(o) {
|
|
|
252 |
var sType = (Lang.isNull(o) || Lang.isUndefined(o)) ? ('' + o) : typeof o;
|
|
|
253 |
return 'type=' + sType + '&value=' + encodeURIComponent('' + o);
|
|
|
254 |
},
|
|
|
255 |
|
|
|
256 |
/**
|
|
|
257 |
* Implementation of the getItem login; should be overwritten by storage engine.
|
|
|
258 |
* @method _getItem
|
|
|
259 |
* @param sKey {String} Required. The key used to reference this value.
|
|
|
260 |
* @return {String|NULL} The value stored at the provided key.
|
|
|
261 |
* @protected
|
|
|
262 |
*/
|
|
|
263 |
_getItem: function(sKey) {
|
|
|
264 |
_logOverwriteError('_getItem');
|
|
|
265 |
return '';
|
|
|
266 |
},
|
|
|
267 |
|
|
|
268 |
/**
|
|
|
269 |
* Converts the stored value into its appropriate type.
|
|
|
270 |
* @method _getValue
|
|
|
271 |
* @param s {String} Required. The stored value.
|
|
|
272 |
* @protected
|
|
|
273 |
*/
|
|
|
274 |
_getValue: function(s) {
|
|
|
275 |
var sType = s.match(RX_TYPE)[1],
|
|
|
276 |
sValue = s.match(RX_VALUE)[1];
|
|
|
277 |
|
|
|
278 |
switch (sType) {
|
|
|
279 |
case 'boolean': return 'true' == sValue;
|
|
|
280 |
case 'number': return parseFloat(sValue);
|
|
|
281 |
case 'null': return null;
|
|
|
282 |
default: return decodeURIComponent(sValue);
|
|
|
283 |
}
|
|
|
284 |
},
|
|
|
285 |
|
|
|
286 |
/**
|
|
|
287 |
* Implementation of the key logic; should be overwritten by storage engine.
|
|
|
288 |
* @method _key
|
|
|
289 |
* @param nIndex {Number} Required. The index to retrieve (unsigned long in HTML 5 spec).
|
|
|
290 |
* @return {String|NULL} Required. The key at the provided index (DOMString in HTML 5 spec).
|
|
|
291 |
* @protected
|
|
|
292 |
*/
|
|
|
293 |
_key: function(nIndex) {
|
|
|
294 |
_logOverwriteError('_key');
|
|
|
295 |
return '';
|
|
|
296 |
},
|
|
|
297 |
|
|
|
298 |
/*
|
|
|
299 |
* Implementation to fetch evaluate the existence of a key.
|
|
|
300 |
*/
|
|
|
301 |
_hasKey: function(sKey) {
|
|
|
302 |
return null !== this._getItem(sKey);
|
|
|
303 |
},
|
|
|
304 |
|
|
|
305 |
/**
|
|
|
306 |
* Implementation of the removeItem login; should be overwritten by storage engine.
|
|
|
307 |
* @method _removeItem
|
|
|
308 |
* @param sKey {String} Required. The key to remove.
|
|
|
309 |
* @protected
|
|
|
310 |
*/
|
|
|
311 |
_removeItem: function(sKey) {
|
|
|
312 |
_logOverwriteError('_removeItem');
|
|
|
313 |
return '';
|
|
|
314 |
},
|
|
|
315 |
|
|
|
316 |
/**
|
|
|
317 |
* Implementation of the setItem login; should be overwritten by storage engine.
|
|
|
318 |
* @method _setItem
|
|
|
319 |
* @param sKey {String} Required. The key used to reference this value.
|
|
|
320 |
* @param oData {Object} Required. The data to storage at key.
|
|
|
321 |
* @return {Boolean} True when successful, false when size QUOTA exceeded.
|
|
|
322 |
* @protected
|
|
|
323 |
*/
|
|
|
324 |
_setItem: function(sKey, oData) {
|
|
|
325 |
_logOverwriteError('_setItem');
|
|
|
326 |
return '';
|
|
|
327 |
}
|
|
|
328 |
};
|
|
|
329 |
|
|
|
330 |
Lang.augmentProto(Storage, Util.EventProvider);
|
|
|
331 |
|
|
|
332 |
Util.Storage = Storage;
|
|
|
333 |
}
|
|
|
334 |
|
|
|
335 |
}());
|
|
|
336 |
/**
|
|
|
337 |
* The StorageManager class is a singleton that registers DataStorage objects and returns instances of those objects.
|
|
|
338 |
* @class StorageManager
|
|
|
339 |
* @namespace YAHOO.util
|
|
|
340 |
* @static
|
|
|
341 |
*/
|
|
|
342 |
(function() {
|
|
|
343 |
// internal shorthand
|
|
|
344 |
var Util = YAHOO.util,
|
|
|
345 |
Lang = YAHOO.lang,
|
|
|
346 |
|
|
|
347 |
// private variables
|
|
|
348 |
_locationEngineMap = {}, // cached engines
|
|
|
349 |
_registeredEngineSet = [], // set of available engines
|
|
|
350 |
_registeredEngineMap = {}, // map of available engines
|
|
|
351 |
|
|
|
352 |
/**
|
|
|
353 |
* Fetches a storage constructor if it is available, otherwise returns NULL.
|
|
|
354 |
* @method _getClass
|
|
|
355 |
* @param fnClass {Function} Required. The storage constructor to test.
|
|
|
356 |
* @return {Function} An available storage constructor or NULL.
|
|
|
357 |
* @private
|
|
|
358 |
*/
|
|
|
359 |
_getClass = function(fnClass) {
|
|
|
360 |
return (fnClass && fnClass.isAvailable()) ? fnClass : null;
|
|
|
361 |
},
|
|
|
362 |
|
|
|
363 |
/**
|
|
|
364 |
* Fetches the storage engine from the cache, or creates and caches it.
|
|
|
365 |
* @method _getStorageEngine
|
|
|
366 |
* @param sLocation {String} Required. The location to store.
|
|
|
367 |
* @param fnClass {Function} Required. A pointer to the engineType Class.
|
|
|
368 |
* @param oConf {Object} Optional. Additional configuration for the data source engine.
|
|
|
369 |
* @private
|
|
|
370 |
*/
|
|
|
371 |
_getStorageEngine = function(sLocation, fnClass, oConf) {
|
|
|
372 |
var engine = _locationEngineMap[sLocation + fnClass.ENGINE_NAME];
|
|
|
373 |
|
|
|
374 |
if (! engine) {
|
|
|
375 |
engine = new fnClass(sLocation, oConf);
|
|
|
376 |
_locationEngineMap[sLocation + fnClass.ENGINE_NAME] = engine;
|
|
|
377 |
}
|
|
|
378 |
|
|
|
379 |
return engine;
|
|
|
380 |
},
|
|
|
381 |
|
|
|
382 |
/**
|
|
|
383 |
* Ensures that the location is valid before returning it or a default value.
|
|
|
384 |
* @method _getValidLocation
|
|
|
385 |
* @param sLocation {String} Required. The location to evaluate.
|
|
|
386 |
* @private
|
|
|
387 |
*/
|
|
|
388 |
_getValidLocation = function(sLocation) {
|
|
|
389 |
switch (sLocation) {
|
|
|
390 |
case Util.StorageManager.LOCATION_LOCAL:
|
|
|
391 |
case Util.StorageManager.LOCATION_SESSION:
|
|
|
392 |
return sLocation;
|
|
|
393 |
|
|
|
394 |
default: return Util.StorageManager.LOCATION_SESSION;
|
|
|
395 |
}
|
|
|
396 |
};
|
|
|
397 |
|
|
|
398 |
// public namespace
|
|
|
399 |
Util.StorageManager = {
|
|
|
400 |
|
|
|
401 |
/**
|
|
|
402 |
* The storage location - session; data cleared at the end of a user's session.
|
|
|
403 |
* @property LOCATION_SESSION
|
|
|
404 |
* @type {String}
|
|
|
405 |
* @static
|
|
|
406 |
*/
|
|
|
407 |
LOCATION_SESSION: 'sessionStorage',
|
|
|
408 |
|
|
|
409 |
/**
|
|
|
410 |
* The storage location - local; data cleared on demand.
|
|
|
411 |
* @property LOCATION_LOCAL
|
|
|
412 |
* @type {String}
|
|
|
413 |
* @static
|
|
|
414 |
*/
|
|
|
415 |
LOCATION_LOCAL: 'localStorage',
|
|
|
416 |
|
|
|
417 |
/**
|
|
|
418 |
* Fetches the desired engine type or first available engine type.
|
|
|
419 |
* @method get
|
|
|
420 |
* @param engineType {String} Optional. The engine type, see engines.
|
|
|
421 |
* @param sLocation {String} Optional. The storage location - LOCATION_SESSION & LOCATION_LOCAL; default is LOCAL.
|
|
|
422 |
* @param oConf {Object} Optional. Additional configuration for the getting the storage engine.
|
|
|
423 |
* {
|
|
|
424 |
* engine: {Object} configuration parameters for the desired engine
|
|
|
425 |
* force: {Boolean} force the <code>engineType</code> or fail
|
|
|
426 |
* order: {Array} an array of storage engine names; the desired order to try engines}
|
|
|
427 |
* }
|
|
|
428 |
* @static
|
|
|
429 |
*/
|
|
|
430 |
get: function(engineType, sLocation, oConf) {
|
|
|
431 |
var oCfg = Lang.isObject(oConf) ? oConf : {},
|
|
|
432 |
fnClass = _getClass(_registeredEngineMap[engineType]),
|
|
|
433 |
i , j;
|
|
|
434 |
|
|
|
435 |
if (! fnClass && ! oCfg.force) {
|
|
|
436 |
if (oCfg.order) {
|
|
|
437 |
j = oCfg.order.length;
|
|
|
438 |
|
|
|
439 |
for (i = 0; i < j && ! fnClass; i += 1) {
|
|
|
440 |
fnClass = _getClass(oCfg.order[i]);
|
|
|
441 |
}
|
|
|
442 |
}
|
|
|
443 |
|
|
|
444 |
if (! fnClass) {
|
|
|
445 |
j = _registeredEngineSet.length;
|
|
|
446 |
|
|
|
447 |
for (i = 0; i < j && ! fnClass; i += 1) {
|
|
|
448 |
fnClass = _getClass(_registeredEngineSet[i]);
|
|
|
449 |
}
|
|
|
450 |
}
|
|
|
451 |
}
|
|
|
452 |
|
|
|
453 |
if (fnClass) {
|
|
|
454 |
return _getStorageEngine(_getValidLocation(sLocation), fnClass, oCfg.engine);
|
|
|
455 |
}
|
|
|
456 |
|
|
|
457 |
throw('YAHOO.util.StorageManager.get - No engine available, please include an engine before calling this function.');
|
|
|
458 |
},
|
|
|
459 |
|
|
|
460 |
/*
|
|
|
461 |
* Estimates the size of the string using 1 byte for each alpha-numeric character and 3 for each non-alpha-numeric character.
|
|
|
462 |
* @method getByteSize
|
|
|
463 |
* @param s {String} Required. The string to evaulate.
|
|
|
464 |
* @return {Number} The estimated string size.
|
|
|
465 |
* @private
|
|
|
466 |
*/
|
|
|
467 |
getByteSize: function(s) {
|
|
|
468 |
return encodeURIComponent('' + s).length;
|
|
|
469 |
},
|
|
|
470 |
|
|
|
471 |
/**
|
|
|
472 |
* Registers a engineType Class with the StorageManager singleton; first in is the first out.
|
|
|
473 |
* @method register
|
|
|
474 |
* @param engineConstructor {Function} Required. The engine constructor function, see engines.
|
|
|
475 |
* @return {Boolean} When successfully registered.
|
|
|
476 |
* @static
|
|
|
477 |
*/
|
|
|
478 |
register: function(engineConstructor) {
|
|
|
479 |
if (Lang.isFunction(engineConstructor) && Lang.isFunction(engineConstructor.isAvailable) &&
|
|
|
480 |
Lang.isString(engineConstructor.ENGINE_NAME)) {
|
|
|
481 |
_registeredEngineMap[engineConstructor.ENGINE_NAME] = engineConstructor;
|
|
|
482 |
_registeredEngineSet.push(engineConstructor);
|
|
|
483 |
return true;
|
|
|
484 |
}
|
|
|
485 |
|
|
|
486 |
return false;
|
|
|
487 |
}
|
|
|
488 |
};
|
|
|
489 |
|
|
|
490 |
YAHOO.register("StorageManager", Util.SWFStore, {version: "2.9.0", build: "2800"});
|
|
|
491 |
}());
|
|
|
492 |
(function() {
|
|
|
493 |
|
|
|
494 |
/**
|
|
|
495 |
* The StorageEvent class manages the storage events by emulating the HTML 5 implementation.
|
|
|
496 |
* @namespace YAHOO.util
|
|
|
497 |
* @class StorageEvent
|
|
|
498 |
* @constructor
|
|
|
499 |
* @param oStorageArea {Object} Required. The Storage object that was affected.
|
|
|
500 |
* @param sKey {String} Required. The key being changed; DOMString in HTML 5 spec.
|
|
|
501 |
* @param oOldValue {Mixed} Required. The old value of the key being changed; DOMString in HTML 5 spec.
|
|
|
502 |
* @param oNewValue {Mixed} Required. The new value of the key being changed; DOMString in HTML 5 spec.
|
|
|
503 |
* @param sType {String} Required. The storage event type.
|
|
|
504 |
*/
|
|
|
505 |
function StorageEvent(oStorageArea, sKey, oOldValue, oNewValue, sType) {
|
|
|
506 |
this.key = sKey;
|
|
|
507 |
this.oldValue = oOldValue;
|
|
|
508 |
this.newValue = oNewValue;
|
|
|
509 |
this.url = window.location.href;
|
|
|
510 |
this.window = window; // todo: think about the CAJA and innocent code
|
|
|
511 |
this.storageArea = oStorageArea;
|
|
|
512 |
this.type = sType;
|
|
|
513 |
}
|
|
|
514 |
|
|
|
515 |
YAHOO.lang.augmentObject(StorageEvent, {
|
|
|
516 |
TYPE_ADD_ITEM: 'addItem',
|
|
|
517 |
TYPE_REMOVE_ITEM: 'removeItem',
|
|
|
518 |
TYPE_UPDATE_ITEM: 'updateItem'
|
|
|
519 |
});
|
|
|
520 |
|
|
|
521 |
StorageEvent.prototype = {
|
|
|
522 |
|
|
|
523 |
/**
|
|
|
524 |
* The 'key' attribute represents the key being changed.
|
|
|
525 |
* @property key
|
|
|
526 |
* @type {String}
|
|
|
527 |
* @static
|
|
|
528 |
* @readonly
|
|
|
529 |
*/
|
|
|
530 |
key: null,
|
|
|
531 |
|
|
|
532 |
/**
|
|
|
533 |
* The 'newValue' attribute represents the new value of the key being changed.
|
|
|
534 |
* @property newValue
|
|
|
535 |
* @type {Mixed}
|
|
|
536 |
* @static
|
|
|
537 |
* @readonly
|
|
|
538 |
*/
|
|
|
539 |
newValue: null,
|
|
|
540 |
|
|
|
541 |
/**
|
|
|
542 |
* The 'oldValue' attribute represents the old value of the key being changed.
|
|
|
543 |
* @property oldValue
|
|
|
544 |
* @type {Mixed}
|
|
|
545 |
* @static
|
|
|
546 |
* @readonly
|
|
|
547 |
*/
|
|
|
548 |
oldValue: null,
|
|
|
549 |
|
|
|
550 |
/**
|
|
|
551 |
* The 'source' attribute represents the WindowProxy object of the browsing context of the document whose key changed.
|
|
|
552 |
* @property source
|
|
|
553 |
* @type {Object}
|
|
|
554 |
* @static
|
|
|
555 |
* @readonly
|
|
|
556 |
*/
|
|
|
557 |
source: null,
|
|
|
558 |
|
|
|
559 |
/**
|
|
|
560 |
* The 'storageArea' attribute represents the Storage object that was affected.
|
|
|
561 |
* @property storageArea
|
|
|
562 |
* @type {Object}
|
|
|
563 |
* @static
|
|
|
564 |
* @readonly
|
|
|
565 |
*/
|
|
|
566 |
storageArea: null,
|
|
|
567 |
|
|
|
568 |
/**
|
|
|
569 |
* The 'type' attribute represents the Storage event type.
|
|
|
570 |
* @property type
|
|
|
571 |
* @type {Object}
|
|
|
572 |
* @static
|
|
|
573 |
* @readonly
|
|
|
574 |
*/
|
|
|
575 |
type: null,
|
|
|
576 |
|
|
|
577 |
/**
|
|
|
578 |
* The 'url' attribute represents the address of the document whose key changed.
|
|
|
579 |
* @property url
|
|
|
580 |
* @type {String}
|
|
|
581 |
* @static
|
|
|
582 |
* @readonly
|
|
|
583 |
*/
|
|
|
584 |
url: null
|
|
|
585 |
};
|
|
|
586 |
|
|
|
587 |
YAHOO.util.StorageEvent = StorageEvent;
|
|
|
588 |
|
|
|
589 |
}());
|
|
|
590 |
(function() {
|
|
|
591 |
var Util = YAHOO.util;
|
|
|
592 |
|
|
|
593 |
/**
|
|
|
594 |
* The StorageEngineKeyed class implements the interface necessary for managing keys.
|
|
|
595 |
* @namespace YAHOO.util
|
|
|
596 |
* @class StorageEngineKeyed
|
|
|
597 |
* @constructor
|
|
|
598 |
* @extend YAHOO.util.Storage
|
|
|
599 |
*/
|
|
|
600 |
Util.StorageEngineKeyed = function() {
|
|
|
601 |
Util.StorageEngineKeyed.superclass.constructor.apply(this, arguments);
|
|
|
602 |
this._keys = [];
|
|
|
603 |
this._keyMap = {};
|
|
|
604 |
};
|
|
|
605 |
|
|
|
606 |
YAHOO.lang.extend(Util.StorageEngineKeyed, Util.Storage, {
|
|
|
607 |
|
|
|
608 |
/**
|
|
|
609 |
* A collection of keys applicable to the current location. This should never be edited by the developer.
|
|
|
610 |
* @property _keys
|
|
|
611 |
* @type {Array}
|
|
|
612 |
* @protected
|
|
|
613 |
*/
|
|
|
614 |
_keys: null,
|
|
|
615 |
|
|
|
616 |
/**
|
|
|
617 |
* A map of keys to their applicable position in keys array. This should never be edited by the developer.
|
|
|
618 |
* @property _keyMap
|
|
|
619 |
* @type {Object}
|
|
|
620 |
* @protected
|
|
|
621 |
*/
|
|
|
622 |
_keyMap: null,
|
|
|
623 |
|
|
|
624 |
/**
|
|
|
625 |
* Adds the key to the set.
|
|
|
626 |
* @method _addKey
|
|
|
627 |
* @param sKey {String} Required. The key to evaluate.
|
|
|
628 |
* @protected
|
|
|
629 |
*/
|
|
|
630 |
_addKey: function(sKey) {
|
|
|
631 |
if (!this._keyMap.hasOwnProperty(sKey)) {
|
|
|
632 |
this._keys.push(sKey);
|
|
|
633 |
this._keyMap[sKey] = this.length;
|
|
|
634 |
this.length = this._keys.length;
|
|
|
635 |
}
|
|
|
636 |
},
|
|
|
637 |
|
|
|
638 |
/*
|
|
|
639 |
* Implementation to clear the values from the storage engine.
|
|
|
640 |
* @see YAHOO.util.Storage._clear
|
|
|
641 |
*/
|
|
|
642 |
_clear: function() {
|
|
|
643 |
this._keys = [];
|
|
|
644 |
this.length = 0;
|
|
|
645 |
},
|
|
|
646 |
|
|
|
647 |
/**
|
|
|
648 |
* Evaluates if a key exists in the keys array; indexOf does not work in all flavors of IE.
|
|
|
649 |
* @method _indexOfKey
|
|
|
650 |
* @param sKey {String} Required. The key to evaluate.
|
|
|
651 |
* @protected
|
|
|
652 |
*/
|
|
|
653 |
_indexOfKey: function(sKey) {
|
|
|
654 |
var i = this._keyMap[sKey];
|
|
|
655 |
return undefined === i ? -1 : i;
|
|
|
656 |
},
|
|
|
657 |
|
|
|
658 |
/*
|
|
|
659 |
* Implementation to fetch a key from the storage engine.
|
|
|
660 |
* @see YAHOO.util.Storage.key
|
|
|
661 |
*/
|
|
|
662 |
_key: function(nIndex) {return this._keys[nIndex];},
|
|
|
663 |
|
|
|
664 |
/**
|
|
|
665 |
* Removes a key from the keys array.
|
|
|
666 |
* @method _removeItem
|
|
|
667 |
* @param sKey {String} Required. The key to remove.
|
|
|
668 |
* @protected
|
|
|
669 |
*/
|
|
|
670 |
_removeItem: function(sKey) {
|
|
|
671 |
var that = this,
|
|
|
672 |
j = that._indexOfKey(sKey),
|
|
|
673 |
rest = that._keys.slice(j + 1),
|
|
|
674 |
k;
|
|
|
675 |
|
|
|
676 |
delete that._keyMap[sKey];
|
|
|
677 |
|
|
|
678 |
// update values in keymap that are greater than current position
|
|
|
679 |
for (k in that._keyMap) {
|
|
|
680 |
if (j < that._keyMap[k]) {
|
|
|
681 |
that._keyMap[k] -= 1;
|
|
|
682 |
}
|
|
|
683 |
}
|
|
|
684 |
|
|
|
685 |
that._keys.length = j;
|
|
|
686 |
that._keys = that._keys.concat(rest);
|
|
|
687 |
that.length = that._keys.length;
|
|
|
688 |
}
|
|
|
689 |
});
|
|
|
690 |
}());
|
|
|
691 |
/*
|
|
|
692 |
* HTML limitations:
|
|
|
693 |
* - 5MB in FF and Safari, 10MB in IE 8
|
|
|
694 |
* - only FF 3.5 recovers session storage after a browser crash
|
|
|
695 |
*
|
|
|
696 |
* Thoughts:
|
|
|
697 |
* - how can we not use cookies to handle session
|
|
|
698 |
*/
|
|
|
699 |
(function() {
|
|
|
700 |
// internal shorthand
|
|
|
701 |
var Util = YAHOO.util,
|
|
|
702 |
Lang = YAHOO.lang,
|
|
|
703 |
|
|
|
704 |
/*
|
|
|
705 |
* Required for IE 8 to make synchronous.
|
|
|
706 |
*/
|
|
|
707 |
_beginTransaction = function(driver) {
|
|
|
708 |
driver.begin();
|
|
|
709 |
},
|
|
|
710 |
|
|
|
711 |
/*
|
|
|
712 |
* Required for IE 8 to make synchronous.
|
|
|
713 |
*/
|
|
|
714 |
_commitTransaction = function(driver) {
|
|
|
715 |
driver.commit();
|
|
|
716 |
},
|
|
|
717 |
|
|
|
718 |
/**
|
|
|
719 |
* The StorageEngineHTML5 class implements the HTML5 storage engine.
|
|
|
720 |
* @namespace YAHOO.util
|
|
|
721 |
* @class StorageEngineHTML5
|
|
|
722 |
* @constructor
|
|
|
723 |
* @extend YAHOO.util.Storage
|
|
|
724 |
* @param sLocation {String} Required. The storage location.
|
|
|
725 |
* @param oConf {Object} Required. A configuration object.
|
|
|
726 |
*/
|
|
|
727 |
StorageEngineHTML5 = function(sLocation, oConf) {
|
|
|
728 |
var that = this,
|
|
|
729 |
oDriver = window[sLocation];
|
|
|
730 |
|
|
|
731 |
StorageEngineHTML5.superclass.constructor.call(that, sLocation, StorageEngineHTML5.ENGINE_NAME, oConf);// not set, are cookies available
|
|
|
732 |
|
|
|
733 |
// simplifieds the begin/commit functions, if not using IE; this provides a massive performance boost
|
|
|
734 |
if (! oDriver.begin) {_beginTransaction = function() {}; }
|
|
|
735 |
if (! oDriver.commit) {_commitTransaction = function() {}; }
|
|
|
736 |
|
|
|
737 |
that.length = oDriver.length;
|
|
|
738 |
that._driver = oDriver;
|
|
|
739 |
that.fireEvent(Util.Storage.CE_READY);
|
|
|
740 |
};
|
|
|
741 |
|
|
|
742 |
Lang.extend(StorageEngineHTML5, Util.Storage, {
|
|
|
743 |
|
|
|
744 |
_driver: null,
|
|
|
745 |
|
|
|
746 |
/*
|
|
|
747 |
* Implementation to clear the values from the storage engine.
|
|
|
748 |
* @see YAHOO.util.Storage._clear
|
|
|
749 |
*/
|
|
|
750 |
_clear: function() {
|
|
|
751 |
var that = this, i, sKey;
|
|
|
752 |
|
|
|
753 |
if (that._driver.clear) {
|
|
|
754 |
that._driver.clear();
|
|
|
755 |
}
|
|
|
756 |
// for FF 3, fixed in FF 3.5
|
|
|
757 |
else {
|
|
|
758 |
for (i = that.length; 0 <= i; i -= 1) {
|
|
|
759 |
sKey = that._key(i);
|
|
|
760 |
that._removeItem(sKey);
|
|
|
761 |
}
|
|
|
762 |
}
|
|
|
763 |
},
|
|
|
764 |
|
|
|
765 |
/*
|
|
|
766 |
* Implementation to fetch an item from the storage engine.
|
|
|
767 |
* @see YAHOO.util.Storage._getItem
|
|
|
768 |
*/
|
|
|
769 |
_getItem: function(sKey) {
|
|
|
770 |
var o = this._driver.getItem(sKey);
|
|
|
771 |
return Lang.isObject(o) ? o.value : o; // for FF 3, fixed in FF 3.5
|
|
|
772 |
},
|
|
|
773 |
|
|
|
774 |
/*
|
|
|
775 |
* Implementation to fetch a key from the storage engine.
|
|
|
776 |
* @see YAHOO.util.Storage._key
|
|
|
777 |
*/
|
|
|
778 |
_key: function(nIndex) {return this._driver.key(nIndex);},
|
|
|
779 |
|
|
|
780 |
/*
|
|
|
781 |
* Implementation to remove an item from the storage engine.
|
|
|
782 |
* @see YAHOO.util.Storage._removeItem
|
|
|
783 |
*/
|
|
|
784 |
_removeItem: function(sKey) {
|
|
|
785 |
var oDriver = this._driver;
|
|
|
786 |
_beginTransaction(oDriver);
|
|
|
787 |
oDriver.removeItem(sKey);
|
|
|
788 |
_commitTransaction(oDriver);
|
|
|
789 |
this.length = oDriver.length;
|
|
|
790 |
},
|
|
|
791 |
|
|
|
792 |
/*
|
|
|
793 |
* Implementation to remove an item from the storage engine.
|
|
|
794 |
* @see YAHOO.util.Storage._setItem
|
|
|
795 |
*/
|
|
|
796 |
_setItem: function(sKey, oValue) {
|
|
|
797 |
var oDriver = this._driver;
|
|
|
798 |
|
|
|
799 |
try {
|
|
|
800 |
_beginTransaction(oDriver);
|
|
|
801 |
oDriver.setItem(sKey, oValue);
|
|
|
802 |
_commitTransaction(oDriver);
|
|
|
803 |
this.length = oDriver.length;
|
|
|
804 |
return true;
|
|
|
805 |
}
|
|
|
806 |
catch (e) {
|
|
|
807 |
return false;
|
|
|
808 |
}
|
|
|
809 |
}
|
|
|
810 |
}, true);
|
|
|
811 |
|
|
|
812 |
StorageEngineHTML5.ENGINE_NAME = 'html5';
|
|
|
813 |
|
|
|
814 |
StorageEngineHTML5.isAvailable = function() {
|
|
|
815 |
try {
|
|
|
816 |
return ('localStorage' in window) && window['localStorage'] !== null &&
|
|
|
817 |
('sessionStorage' in window) && window['sessionStorage'] !== null;
|
|
|
818 |
}
|
|
|
819 |
catch (e) {
|
|
|
820 |
/*
|
|
|
821 |
In FireFox and maybe other browsers, you can disable storage in the configuration settings, which
|
|
|
822 |
will cause an error to be thrown instead of evaluating the simple if/else statement.
|
|
|
823 |
*/
|
|
|
824 |
return false;
|
|
|
825 |
}
|
|
|
826 |
};
|
|
|
827 |
|
|
|
828 |
Util.StorageManager.register(StorageEngineHTML5);
|
|
|
829 |
Util.StorageEngineHTML5 = StorageEngineHTML5;
|
|
|
830 |
}());
|
|
|
831 |
/*
|
|
|
832 |
* Gears limitation:
|
|
|
833 |
* - SQLite limitations - http://www.sqlite.org/limits.html
|
|
|
834 |
* - DB Best Practices - http://code.google.com/apis/gears/gears_faq.html#bestPracticeDB
|
|
|
835 |
* - the user must approve before gears can be used
|
|
|
836 |
* - each SQL query has a limited number of characters (9948 bytes), data will need to be spread across rows
|
|
|
837 |
* - no query should insert or update more than 9948 bytes of data in a single statement or GEARs will throw:
|
|
|
838 |
* [Exception... "'Error: SQL statement is too long.' when calling method: [nsIDOMEventListener::handleEvent]" nsresult: "0x8057001c (NS_ERROR_XPC_JS_THREW_JS_OBJECT)" location: "<unknown>" data: no]
|
|
|
839 |
*
|
|
|
840 |
* Thoughts:
|
|
|
841 |
* - we may want to implement additional functions for the gears only implementation
|
|
|
842 |
* - how can we not use cookies to handle session location
|
|
|
843 |
*/
|
|
|
844 |
(function() {
|
|
|
845 |
// internal shorthand
|
|
|
846 |
var Util = YAHOO.util,
|
|
|
847 |
Lang = YAHOO.lang,
|
|
|
848 |
SQL_STMT_LIMIT = 9948,
|
|
|
849 |
TABLE_NAME = 'YUIStorageEngine',
|
|
|
850 |
|
|
|
851 |
// local variables
|
|
|
852 |
_driver = null,
|
|
|
853 |
|
|
|
854 |
eURI = encodeURIComponent,
|
|
|
855 |
dURI = decodeURIComponent,
|
|
|
856 |
|
|
|
857 |
/**
|
|
|
858 |
* The StorageEngineGears class implements the Google Gears storage engine.
|
|
|
859 |
* @namespace YAHOO.util
|
|
|
860 |
* @class StorageEngineGears
|
|
|
861 |
* @constructor
|
|
|
862 |
* @extend YAHOO.util.Storage
|
|
|
863 |
* @param sLocation {String} Required. The storage location.
|
|
|
864 |
* @param oConf {Object} Required. A configuration object.
|
|
|
865 |
*/
|
|
|
866 |
StorageEngineGears = function(sLocation, oConf) {
|
|
|
867 |
var that = this,
|
|
|
868 |
keyMap = {},
|
|
|
869 |
isSessionStorage, sessionKey, rs;
|
|
|
870 |
|
|
|
871 |
StorageEngineGears.superclass.constructor.call(that, sLocation, StorageEngineGears.ENGINE_NAME, oConf);
|
|
|
872 |
|
|
|
873 |
if (! _driver) {
|
|
|
874 |
// create the database
|
|
|
875 |
_driver = google.gears.factory.create(StorageEngineGears.GEARS);
|
|
|
876 |
// the replace regex fixes http://yuilibrary.com/projects/yui2/ticket/2529411, all ascii characters are allowede except / : * ? " < > | ; ,
|
|
|
877 |
_driver.open(window.location.host.replace(/[\/\:\*\?"\<\>\|;,]/g, '') + '-' + StorageEngineGears.DATABASE);
|
|
|
878 |
_driver.execute('CREATE TABLE IF NOT EXISTS ' + TABLE_NAME + ' (key TEXT, location TEXT, value TEXT)');
|
|
|
879 |
}
|
|
|
880 |
|
|
|
881 |
isSessionStorage = Util.StorageManager.LOCATION_SESSION === that._location;
|
|
|
882 |
sessionKey = Util.Cookie.get('sessionKey' + StorageEngineGears.ENGINE_NAME);
|
|
|
883 |
|
|
|
884 |
if (! sessionKey) {
|
|
|
885 |
_driver.execute('BEGIN');
|
|
|
886 |
_driver.execute('DELETE FROM ' + TABLE_NAME + ' WHERE location="' + eURI(Util.StorageManager.LOCATION_SESSION) + '"');
|
|
|
887 |
_driver.execute('COMMIT');
|
|
|
888 |
}
|
|
|
889 |
|
|
|
890 |
rs = _driver.execute('SELECT key FROM ' + TABLE_NAME + ' WHERE location="' + eURI(that._location) + '"');
|
|
|
891 |
keyMap = {};
|
|
|
892 |
|
|
|
893 |
try {
|
|
|
894 |
// iterate on the rows and map the keys
|
|
|
895 |
while (rs.isValidRow()) {
|
|
|
896 |
var fld = dURI(rs.field(0));
|
|
|
897 |
|
|
|
898 |
if (! keyMap[fld]) {
|
|
|
899 |
keyMap[fld] = true;
|
|
|
900 |
that._addKey(fld);
|
|
|
901 |
}
|
|
|
902 |
|
|
|
903 |
rs.next();
|
|
|
904 |
}
|
|
|
905 |
} finally {
|
|
|
906 |
rs.close();
|
|
|
907 |
}
|
|
|
908 |
|
|
|
909 |
// this is session storage, ensure that the session key is set
|
|
|
910 |
if (isSessionStorage) {
|
|
|
911 |
Util.Cookie.set('sessionKey' + StorageEngineGears.ENGINE_NAME, true);
|
|
|
912 |
}
|
|
|
913 |
|
|
|
914 |
that.fireEvent(Util.Storage.CE_READY);
|
|
|
915 |
};
|
|
|
916 |
|
|
|
917 |
Lang.extend(StorageEngineGears, Util.StorageEngineKeyed, {
|
|
|
918 |
|
|
|
919 |
/*
|
|
|
920 |
* Implementation to clear the values from the storage engine.
|
|
|
921 |
* @see YAHOO.util.Storage._clear
|
|
|
922 |
*/
|
|
|
923 |
_clear: function() {
|
|
|
924 |
StorageEngineGears.superclass._clear.call(this);
|
|
|
925 |
_driver.execute('BEGIN');
|
|
|
926 |
_driver.execute('DELETE FROM ' + TABLE_NAME + ' WHERE location="' + eURI(this._location) + '"');
|
|
|
927 |
_driver.execute('COMMIT');
|
|
|
928 |
},
|
|
|
929 |
|
|
|
930 |
/*
|
|
|
931 |
* Implementation to fetch an item from the storage engine.
|
|
|
932 |
* @see YAHOO.util.Storage._getItem
|
|
|
933 |
*/
|
|
|
934 |
_getItem: function(sKey) {
|
|
|
935 |
var rs = _driver.execute('SELECT value FROM ' + TABLE_NAME + ' WHERE key="' + eURI(sKey) + '" AND location="' + eURI(this._location) + '"'),
|
|
|
936 |
value = '';
|
|
|
937 |
|
|
|
938 |
try {
|
|
|
939 |
while (rs.isValidRow()) {
|
|
|
940 |
value += rs.field(0);
|
|
|
941 |
rs.next();
|
|
|
942 |
}
|
|
|
943 |
} finally {
|
|
|
944 |
rs.close();
|
|
|
945 |
}
|
|
|
946 |
|
|
|
947 |
return value ? dURI(value) : null;
|
|
|
948 |
},
|
|
|
949 |
|
|
|
950 |
/*
|
|
|
951 |
* Implementation to remove an item from the storage engine.
|
|
|
952 |
* @see YAHOO.util.Storage._removeItem
|
|
|
953 |
*/
|
|
|
954 |
_removeItem: function(sKey) {
|
|
|
955 |
YAHOO.log("removing gears key: " + sKey);
|
|
|
956 |
StorageEngineGears.superclass._removeItem.call(this, sKey);
|
|
|
957 |
_driver.execute('BEGIN');
|
|
|
958 |
_driver.execute('DELETE FROM ' + TABLE_NAME + ' WHERE key="' + eURI(sKey) + '" AND location="' + eURI(this._location) + '"');
|
|
|
959 |
_driver.execute('COMMIT');
|
|
|
960 |
},
|
|
|
961 |
|
|
|
962 |
/*
|
|
|
963 |
* Implementation to remove an item from the storage engine.
|
|
|
964 |
* @see YAHOO.util.Storage._setItem
|
|
|
965 |
*/
|
|
|
966 |
_setItem: function(sKey, oData) {
|
|
|
967 |
YAHOO.log("SETTING " + oData + " to " + sKey);
|
|
|
968 |
|
|
|
969 |
this._addKey(sKey);
|
|
|
970 |
|
|
|
971 |
var sEscapedKey = eURI(sKey),
|
|
|
972 |
sEscapedLocation = eURI(this._location),
|
|
|
973 |
sEscapedValue = eURI(oData), // escaped twice, maybe not necessary
|
|
|
974 |
aValues = [],
|
|
|
975 |
nLen = SQL_STMT_LIMIT - (sEscapedKey + sEscapedLocation).length,
|
|
|
976 |
i=0, j;
|
|
|
977 |
|
|
|
978 |
// the length of the value exceeds the available space
|
|
|
979 |
if (nLen < sEscapedValue.length) {
|
|
|
980 |
for (j = sEscapedValue.length; i < j; i += nLen) {
|
|
|
981 |
aValues.push(sEscapedValue.substr(i, nLen));
|
|
|
982 |
}
|
|
|
983 |
} else {
|
|
|
984 |
aValues.push(sEscapedValue);
|
|
|
985 |
}
|
|
|
986 |
|
|
|
987 |
// Google recommends using INSERT instead of update, because it is faster
|
|
|
988 |
_driver.execute('BEGIN');
|
|
|
989 |
_driver.execute('DELETE FROM ' + TABLE_NAME + ' WHERE key="' + sEscapedKey + '" AND location="' + sEscapedLocation + '"');
|
|
|
990 |
for (i = 0, j = aValues.length; i < j; i += 1) {
|
|
|
991 |
_driver.execute('INSERT INTO ' + TABLE_NAME + ' VALUES ("' + sEscapedKey + '", "' + sEscapedLocation + '", "' + aValues[i] + '")');
|
|
|
992 |
}
|
|
|
993 |
_driver.execute('COMMIT');
|
|
|
994 |
|
|
|
995 |
return true;
|
|
|
996 |
}
|
|
|
997 |
});
|
|
|
998 |
|
|
|
999 |
// releases the engine when the page unloads
|
|
|
1000 |
Util.Event.on('unload', function() {
|
|
|
1001 |
if (_driver) {_driver.close();}
|
|
|
1002 |
});
|
|
|
1003 |
|
|
|
1004 |
StorageEngineGears.ENGINE_NAME = 'gears';
|
|
|
1005 |
StorageEngineGears.GEARS = 'beta.database';
|
|
|
1006 |
StorageEngineGears.DATABASE = 'yui.database';
|
|
|
1007 |
|
|
|
1008 |
StorageEngineGears.isAvailable = function() {
|
|
|
1009 |
if (('google' in window) && ('gears' in window.google)) {
|
|
|
1010 |
try {
|
|
|
1011 |
// this will throw an exception if the user denies gears
|
|
|
1012 |
google.gears.factory.create(StorageEngineGears.GEARS);
|
|
|
1013 |
return true;
|
|
|
1014 |
}
|
|
|
1015 |
catch (e) {
|
|
|
1016 |
// no need to do anything
|
|
|
1017 |
}
|
|
|
1018 |
}
|
|
|
1019 |
|
|
|
1020 |
return false;
|
|
|
1021 |
};
|
|
|
1022 |
|
|
|
1023 |
Util.StorageManager.register(StorageEngineGears);
|
|
|
1024 |
Util.StorageEngineGears = StorageEngineGears;
|
|
|
1025 |
}());
|
|
|
1026 |
/*
|
|
|
1027 |
* SWF limitation:
|
|
|
1028 |
* - only 100,000 bytes of data may be stored this way
|
|
|
1029 |
* - data is publicly available on user machine
|
|
|
1030 |
*
|
|
|
1031 |
* Thoughts:
|
|
|
1032 |
* - data can be shared across browsers
|
|
|
1033 |
* - how can we not use cookies to handle session location
|
|
|
1034 |
*/
|
|
|
1035 |
(function() {
|
|
|
1036 |
// internal shorthand
|
|
|
1037 |
var Y = YAHOO,
|
|
|
1038 |
Util = Y.util,
|
|
|
1039 |
Lang = Y.lang,
|
|
|
1040 |
Dom = Util.Dom,
|
|
|
1041 |
StorageManager = Util.StorageManager,
|
|
|
1042 |
|
|
|
1043 |
/*
|
|
|
1044 |
* The minimum width required to be able to display the settings panel within the SWF.
|
|
|
1045 |
*/
|
|
|
1046 |
MINIMUM_WIDTH = 215,
|
|
|
1047 |
|
|
|
1048 |
/*
|
|
|
1049 |
* The minimum height required to be able to display the settings panel within the SWF.
|
|
|
1050 |
*/
|
|
|
1051 |
MINIMUM_HEIGHT = 138,
|
|
|
1052 |
|
|
|
1053 |
RX_STORAGE_PREFIX = new RegExp('^(' + StorageManager.LOCATION_SESSION + '|' + StorageManager.LOCATION_LOCAL + ')'),
|
|
|
1054 |
|
|
|
1055 |
// local variables
|
|
|
1056 |
_driver = null,
|
|
|
1057 |
|
|
|
1058 |
/*
|
|
|
1059 |
* Creates a location bound key.
|
|
|
1060 |
*/
|
|
|
1061 |
_getKey = function(that, sKey) {
|
|
|
1062 |
return that._location + sKey;
|
|
|
1063 |
},
|
|
|
1064 |
|
|
|
1065 |
/*
|
|
|
1066 |
* Initializes the engine, if it isn't already initialized.
|
|
|
1067 |
*/
|
|
|
1068 |
_initDriver = function(oCfg) {
|
|
|
1069 |
if (! _driver) {
|
|
|
1070 |
if (! Lang.isString(oCfg.swfURL)) {oCfg.swfURL = StorageEngineSWF.SWFURL;}
|
|
|
1071 |
if (! oCfg.containerID) {
|
|
|
1072 |
var bd = document.getElementsByTagName('body')[0],
|
|
|
1073 |
container = bd.appendChild(document.createElement('div'));
|
|
|
1074 |
oCfg.containerID = Dom.generateId(container);
|
|
|
1075 |
}
|
|
|
1076 |
|
|
|
1077 |
if (! oCfg.attributes) {oCfg.attributes = {};}
|
|
|
1078 |
if (! oCfg.attributes.flashVars) {oCfg.attributes.flashVars = {};}
|
|
|
1079 |
oCfg.attributes.flashVars.allowedDomain = document.location.hostname;
|
|
|
1080 |
oCfg.attributes.flashVars.useCompression = 'true';
|
|
|
1081 |
oCfg.attributes.version = 9.115;
|
|
|
1082 |
_driver = new Y.widget.SWF(oCfg.containerID, oCfg.swfURL, oCfg.attributes);
|
|
|
1083 |
|
|
|
1084 |
// subscribe to save for info
|
|
|
1085 |
_driver.subscribe('save', function(o) {
|
|
|
1086 |
Y.log(o.message, 'info');
|
|
|
1087 |
});
|
|
|
1088 |
|
|
|
1089 |
// subscribe to errors
|
|
|
1090 |
_driver.subscribe('quotaExceededError', function(o) {
|
|
|
1091 |
Y.log(o.message, 'error');
|
|
|
1092 |
});
|
|
|
1093 |
_driver.subscribe('inadequateDimensions', function(o) {
|
|
|
1094 |
Y.log(o.message, 'error');
|
|
|
1095 |
});
|
|
|
1096 |
_driver.subscribe('error', function(o) {
|
|
|
1097 |
Y.log(o.message, 'error');
|
|
|
1098 |
});
|
|
|
1099 |
_driver.subscribe('securityError', function(o) {
|
|
|
1100 |
Y.log(o.message, 'error');
|
|
|
1101 |
});
|
|
|
1102 |
}
|
|
|
1103 |
},
|
|
|
1104 |
|
|
|
1105 |
/**
|
|
|
1106 |
* The StorageEngineSWF class implements the SWF storage engine.
|
|
|
1107 |
* @namespace YAHOO.util
|
|
|
1108 |
* @class StorageEngineSWF
|
|
|
1109 |
* @uses YAHOO.widget.SWF
|
|
|
1110 |
* @constructor
|
|
|
1111 |
* @extend YAHOO.util.Storage
|
|
|
1112 |
* @param sLocation {String} Required. The storage location.
|
|
|
1113 |
* @param oConf {Object} Required. A configuration object.
|
|
|
1114 |
*/
|
|
|
1115 |
StorageEngineSWF = function(sLocation, oConf) {
|
|
|
1116 |
var that = this;
|
|
|
1117 |
StorageEngineSWF.superclass.constructor.call(that, sLocation, StorageEngineSWF.ENGINE_NAME, oConf);
|
|
|
1118 |
|
|
|
1119 |
_initDriver(that._cfg);
|
|
|
1120 |
|
|
|
1121 |
var _onContentReady = function() {
|
|
|
1122 |
that._swf = _driver._swf;
|
|
|
1123 |
_driver.initialized = true;
|
|
|
1124 |
|
|
|
1125 |
var isSessionStorage = StorageManager.LOCATION_SESSION === that._location,
|
|
|
1126 |
sessionKey = Util.Cookie.get('sessionKey' + StorageEngineSWF.ENGINE_NAME),
|
|
|
1127 |
i, key, isKeySessionStorage;
|
|
|
1128 |
|
|
|
1129 |
for (i = _driver.callSWF("getLength", []) - 1; 0 <= i; i -= 1) {
|
|
|
1130 |
key = _driver.callSWF("getNameAt", [i]);
|
|
|
1131 |
isKeySessionStorage = isSessionStorage && (-1 < key.indexOf(StorageManager.LOCATION_SESSION));
|
|
|
1132 |
|
|
|
1133 |
// this is session storage, but the session key is not set, so remove item
|
|
|
1134 |
if (isKeySessionStorage && ! sessionKey) {
|
|
|
1135 |
_driver.callSWF("removeItem", [key]);
|
|
|
1136 |
}
|
|
|
1137 |
else if (isSessionStorage === isKeySessionStorage) {
|
|
|
1138 |
// the key matches the storage type, add to key collection
|
|
|
1139 |
that._addKey(key);
|
|
|
1140 |
}
|
|
|
1141 |
}
|
|
|
1142 |
|
|
|
1143 |
// this is session storage, ensure that the session key is set
|
|
|
1144 |
if (isSessionStorage) {
|
|
|
1145 |
Util.Cookie.set('sessionKey' + StorageEngineSWF.ENGINE_NAME, true);
|
|
|
1146 |
}
|
|
|
1147 |
|
|
|
1148 |
that.fireEvent(Util.Storage.CE_READY);
|
|
|
1149 |
};
|
|
|
1150 |
|
|
|
1151 |
// evaluate immediately, SWF is already loaded
|
|
|
1152 |
if (_driver.initialized) {
|
|
|
1153 |
_onContentReady();
|
|
|
1154 |
}
|
|
|
1155 |
else {
|
|
|
1156 |
// evaluates when the SWF is loaded
|
|
|
1157 |
_driver.addListener("contentReady", _onContentReady);
|
|
|
1158 |
}
|
|
|
1159 |
};
|
|
|
1160 |
|
|
|
1161 |
Lang.extend(StorageEngineSWF, Util.StorageEngineKeyed, {
|
|
|
1162 |
/**
|
|
|
1163 |
* The underlying SWF of the engine, exposed so developers can modify the adapter behavior.
|
|
|
1164 |
* @property _swf
|
|
|
1165 |
* @type {Object}
|
|
|
1166 |
* @protected
|
|
|
1167 |
*/
|
|
|
1168 |
_swf: null,
|
|
|
1169 |
|
|
|
1170 |
/*
|
|
|
1171 |
* Implementation to clear the values from the storage engine.
|
|
|
1172 |
* @see YAHOO.util.Storage._clear
|
|
|
1173 |
*/
|
|
|
1174 |
_clear: function() {
|
|
|
1175 |
for (var i = this._keys.length - 1, sKey; 0 <= i; i -= 1) {
|
|
|
1176 |
sKey = this._keys[i];
|
|
|
1177 |
_driver.callSWF("removeItem", [sKey]);
|
|
|
1178 |
}
|
|
|
1179 |
// since keys are used to clear, we call the super function second
|
|
|
1180 |
StorageEngineSWF.superclass._clear.call(this);
|
|
|
1181 |
},
|
|
|
1182 |
|
|
|
1183 |
/*
|
|
|
1184 |
* Implementation to fetch an item from the storage engine.
|
|
|
1185 |
* @see YAHOO.util.Storage._getItem
|
|
|
1186 |
*/
|
|
|
1187 |
_getItem: function(sKey) {
|
|
|
1188 |
var sLocationKey = _getKey(this, sKey);
|
|
|
1189 |
return _driver.callSWF("getValueOf", [sLocationKey]);
|
|
|
1190 |
},
|
|
|
1191 |
|
|
|
1192 |
/*
|
|
|
1193 |
* Implementation to fetch a key from the storage engine.
|
|
|
1194 |
* @see YAHOO.util.Storage.key
|
|
|
1195 |
*/
|
|
|
1196 |
_key: function(index) {
|
|
|
1197 |
return StorageEngineSWF.superclass._key.call(this, index).replace(RX_STORAGE_PREFIX, '');
|
|
|
1198 |
},
|
|
|
1199 |
|
|
|
1200 |
/*
|
|
|
1201 |
* Implementation to remove an item from the storage engine.
|
|
|
1202 |
* @see YAHOO.util.Storage._removeItem
|
|
|
1203 |
*/
|
|
|
1204 |
_removeItem: function(sKey) {
|
|
|
1205 |
Y.log("removing SWF key: " + sKey);
|
|
|
1206 |
var sLocationKey = _getKey(this, sKey);
|
|
|
1207 |
StorageEngineSWF.superclass._removeItem.call(this, sLocationKey);
|
|
|
1208 |
_driver.callSWF("removeItem", [sLocationKey]);
|
|
|
1209 |
},
|
|
|
1210 |
|
|
|
1211 |
/*
|
|
|
1212 |
* Implementation to remove an item from the storage engine.
|
|
|
1213 |
* @see YAHOO.util.Storage._setItem
|
|
|
1214 |
*/
|
|
|
1215 |
_setItem: function(sKey, oData) {
|
|
|
1216 |
var sLocationKey = _getKey(this, sKey), swfNode;
|
|
|
1217 |
|
|
|
1218 |
if (_driver.callSWF("setItem", [sLocationKey, oData])) {
|
|
|
1219 |
this._addKey(sLocationKey);
|
|
|
1220 |
return true;
|
|
|
1221 |
}
|
|
|
1222 |
else {
|
|
|
1223 |
/*
|
|
|
1224 |
note:
|
|
|
1225 |
right if the FLASH SLO size needs to be adjusted, then this request and all future requests fail
|
|
|
1226 |
should we queue these up and poll for when there is enough space?
|
|
|
1227 |
*/
|
|
|
1228 |
swfNode = Dom.get(_driver._id);
|
|
|
1229 |
if (MINIMUM_WIDTH > Dom.getStyle(swfNode, 'width').replace(/\D+/g, '')) {Dom.setStyle(swfNode, 'width', MINIMUM_WIDTH + 'px');}
|
|
|
1230 |
if (MINIMUM_HEIGHT > Dom.getStyle(swfNode, 'height').replace(/\D+/g, '')) {Dom.setStyle(swfNode, 'height', MINIMUM_HEIGHT + 'px');}
|
|
|
1231 |
Y.log("attempting to show settings. are dimensions adequate? " + _driver.callSWF("hasAdequateDimensions"));
|
|
|
1232 |
return _driver.callSWF("displaySettings", []);
|
|
|
1233 |
}
|
|
|
1234 |
}
|
|
|
1235 |
});
|
|
|
1236 |
|
|
|
1237 |
StorageEngineSWF.SWFURL = "swfstore.swf";
|
|
|
1238 |
StorageEngineSWF.ENGINE_NAME = 'swf';
|
|
|
1239 |
|
|
|
1240 |
StorageEngineSWF.isAvailable = function() {
|
|
|
1241 |
return (6 <= Y.env.ua.flash && Y.widget.SWF);
|
|
|
1242 |
};
|
|
|
1243 |
|
|
|
1244 |
StorageManager.register(StorageEngineSWF);
|
|
|
1245 |
Util.StorageEngineSWF = StorageEngineSWF;
|
|
|
1246 |
}());
|
|
|
1247 |
YAHOO.register("storage", YAHOO.util.Storage, {version: "2.9.0", build: "2800"});
|
|
|
1248 |
|
|
|
1249 |
}, '2.9.0' ,{"requires": ["yui2-yahoo", "yui2-event", "yui2-cookie"], "optional": ["yui2-dom", "yui2-element", "yui2-swf", "yui2-swfstore"]});
|