Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
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"]});