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
			StorageEngineGears.superclass._removeItem.call(this, sKey);
956
			_driver.execute('BEGIN');
957
			_driver.execute('DELETE FROM ' + TABLE_NAME + ' WHERE key="' + eURI(sKey) + '" AND location="' + eURI(this._location) + '"');
958
			_driver.execute('COMMIT');
959
		},
960
 
961
		/*
962
		 * Implementation to remove an item from the storage engine.
963
		 * @see YAHOO.util.Storage._setItem
964
		 */
965
		_setItem: function(sKey, oData) {
966
 
967
			this._addKey(sKey);
968
 
969
			var sEscapedKey = eURI(sKey),
970
				sEscapedLocation = eURI(this._location),
971
				sEscapedValue = eURI(oData), // escaped twice, maybe not necessary
972
				aValues = [],
973
				nLen = SQL_STMT_LIMIT - (sEscapedKey + sEscapedLocation).length,
974
                i=0, j;
975
 
976
			// the length of the value exceeds the available space
977
			if (nLen < sEscapedValue.length) {
978
				for (j = sEscapedValue.length; i < j; i += nLen) {
979
					aValues.push(sEscapedValue.substr(i, nLen));
980
				}
981
			} else {
982
				aValues.push(sEscapedValue);
983
			}
984
 
985
			// Google recommends using INSERT instead of update, because it is faster
986
			_driver.execute('BEGIN');
987
			_driver.execute('DELETE FROM ' + TABLE_NAME + ' WHERE key="' + sEscapedKey + '" AND location="' + sEscapedLocation + '"');
988
			for (i = 0, j = aValues.length; i < j; i += 1) {
989
				_driver.execute('INSERT INTO ' + TABLE_NAME + ' VALUES ("' + sEscapedKey + '", "' + sEscapedLocation + '", "' + aValues[i] + '")');
990
			}
991
			_driver.execute('COMMIT');
992
 
993
			return true;
994
		}
995
	});
996
 
997
	// releases the engine when the page unloads
998
	Util.Event.on('unload', function() {
999
		if (_driver) {_driver.close();}
1000
	});
1001
 
1002
    StorageEngineGears.ENGINE_NAME = 'gears';
1003
	StorageEngineGears.GEARS = 'beta.database';
1004
	StorageEngineGears.DATABASE = 'yui.database';
1005
 
1006
	StorageEngineGears.isAvailable = function() {
1007
		if (('google' in window) && ('gears' in window.google)) {
1008
			try {
1009
				// this will throw an exception if the user denies gears
1010
				google.gears.factory.create(StorageEngineGears.GEARS);
1011
				return true;
1012
			}
1013
			catch (e) {
1014
				// no need to do anything
1015
			}
1016
		}
1017
 
1018
		return false;
1019
	};
1020
 
1021
    Util.StorageManager.register(StorageEngineGears);
1022
	Util.StorageEngineGears = StorageEngineGears;
1023
}());
1024
/*
1025
 * SWF limitation:
1026
 * 	- only 100,000 bytes of data may be stored this way
1027
 *  - data is publicly available on user machine
1028
 *
1029
 * Thoughts:
1030
 *  - data can be shared across browsers
1031
 *  - how can we not use cookies to handle session location
1032
 */
1033
(function() {
1034
	// internal shorthand
1035
var Y = YAHOO,
1036
    Util = Y.util,
1037
	Lang = Y.lang,
1038
	Dom = Util.Dom,
1039
	StorageManager = Util.StorageManager,
1040
 
1041
	/*
1042
	 * The minimum width required to be able to display the settings panel within the SWF.
1043
	 */
1044
	MINIMUM_WIDTH = 215,
1045
 
1046
	/*
1047
	 * The minimum height required to be able to display the settings panel within the SWF.
1048
	 */
1049
	MINIMUM_HEIGHT = 138,
1050
 
1051
	RX_STORAGE_PREFIX = new RegExp('^(' + StorageManager.LOCATION_SESSION + '|' + StorageManager.LOCATION_LOCAL + ')'),
1052
 
1053
	// local variables
1054
	_driver = null,
1055
 
1056
	/*
1057
	 * Creates a location bound key.
1058
	 */
1059
	_getKey = function(that, sKey) {
1060
		return that._location + sKey;
1061
	},
1062
 
1063
	/*
1064
	 * Initializes the engine, if it isn't already initialized.
1065
	 */
1066
	_initDriver = function(oCfg) {
1067
		if (! _driver) {
1068
			if (! Lang.isString(oCfg.swfURL)) {oCfg.swfURL = StorageEngineSWF.SWFURL;}
1069
			if (! oCfg.containerID) {
1070
				var bd = document.getElementsByTagName('body')[0],
1071
					container = bd.appendChild(document.createElement('div'));
1072
				oCfg.containerID = Dom.generateId(container);
1073
			}
1074
 
1075
			if (! oCfg.attributes) {oCfg.attributes  = {};}
1076
			if (! oCfg.attributes.flashVars) {oCfg.attributes.flashVars = {};}
1077
			oCfg.attributes.flashVars.allowedDomain = document.location.hostname;
1078
			oCfg.attributes.flashVars.useCompression = 'true';
1079
			oCfg.attributes.version = 9.115;
1080
			_driver = new Y.widget.SWF(oCfg.containerID, oCfg.swfURL, oCfg.attributes);
1081
 
1082
			// subscribe to save for info
1083
			_driver.subscribe('save', function(o) {
1084
				Y.log(o.message, 'info');
1085
			});
1086
 
1087
			// subscribe to errors
1088
			_driver.subscribe('quotaExceededError', function(o) {
1089
				Y.log(o.message, 'error');
1090
			});
1091
			_driver.subscribe('inadequateDimensions', function(o) {
1092
				Y.log(o.message, 'error');
1093
			});
1094
			_driver.subscribe('error', function(o) {
1095
				Y.log(o.message, 'error');
1096
			});
1097
			_driver.subscribe('securityError', function(o) {
1098
				Y.log(o.message, 'error');
1099
			});
1100
		}
1101
	},
1102
 
1103
	/**
1104
	 * The StorageEngineSWF class implements the SWF storage engine.
1105
	 * @namespace YAHOO.util
1106
	 * @class StorageEngineSWF
1107
	 * @uses YAHOO.widget.SWF
1108
	 * @constructor
1109
	 * @extend YAHOO.util.Storage
1110
	 * @param sLocation {String} Required. The storage location.
1111
	 * @param oConf {Object} Required. A configuration object.
1112
	 */
1113
	StorageEngineSWF = function(sLocation, oConf) {
1114
		var that = this;
1115
		StorageEngineSWF.superclass.constructor.call(that, sLocation, StorageEngineSWF.ENGINE_NAME, oConf);
1116
 
1117
		_initDriver(that._cfg);
1118
 
1119
		var _onContentReady = function() {
1120
			that._swf = _driver._swf;
1121
			_driver.initialized = true;
1122
 
1123
			var isSessionStorage = StorageManager.LOCATION_SESSION === that._location,
1124
				sessionKey = Util.Cookie.get('sessionKey' + StorageEngineSWF.ENGINE_NAME),
1125
                i, key, isKeySessionStorage;
1126
 
1127
			for (i = _driver.callSWF("getLength", []) - 1; 0 <= i; i -= 1) {
1128
				key = _driver.callSWF("getNameAt", [i]);
1129
				isKeySessionStorage = isSessionStorage && (-1 < key.indexOf(StorageManager.LOCATION_SESSION));
1130
 
1131
				// this is session storage, but the session key is not set, so remove item
1132
				if (isKeySessionStorage && ! sessionKey) {
1133
					_driver.callSWF("removeItem", [key]);
1134
				}
1135
				else if (isSessionStorage === isKeySessionStorage) {
1136
                    // the key matches the storage type, add to key collection
1137
					that._addKey(key);
1138
				}
1139
			}
1140
 
1141
			// this is session storage, ensure that the session key is set
1142
			if (isSessionStorage) {
1143
				Util.Cookie.set('sessionKey' + StorageEngineSWF.ENGINE_NAME, true);
1144
			}
1145
 
1146
			that.fireEvent(Util.Storage.CE_READY);
1147
		};
1148
 
1149
		// evaluate immediately, SWF is already loaded
1150
		if (_driver.initialized) {
1151
            _onContentReady();
1152
		}
1153
		else {
1154
            // evaluates when the SWF is loaded
1155
			_driver.addListener("contentReady", _onContentReady);
1156
		}
1157
	};
1158
 
1159
	Lang.extend(StorageEngineSWF, Util.StorageEngineKeyed, {
1160
		/**
1161
		 * The underlying SWF of the engine, exposed so developers can modify the adapter behavior.
1162
		 * @property _swf
1163
		 * @type {Object}
1164
		 * @protected
1165
		 */
1166
		_swf: null,
1167
 
1168
		/*
1169
		 * Implementation to clear the values from the storage engine.
1170
		 * @see YAHOO.util.Storage._clear
1171
		 */
1172
		_clear: function() {
1173
			for (var i = this._keys.length - 1, sKey; 0 <= i; i -= 1) {
1174
				sKey = this._keys[i];
1175
				_driver.callSWF("removeItem", [sKey]);
1176
			}
1177
			// since keys are used to clear, we call the super function second
1178
			StorageEngineSWF.superclass._clear.call(this);
1179
		},
1180
 
1181
		/*
1182
		 * Implementation to fetch an item from the storage engine.
1183
		 * @see YAHOO.util.Storage._getItem
1184
		 */
1185
		_getItem: function(sKey) {
1186
			var sLocationKey = _getKey(this, sKey);
1187
			return _driver.callSWF("getValueOf", [sLocationKey]);
1188
		},
1189
 
1190
		/*
1191
		 * Implementation to fetch a key from the storage engine.
1192
		 * @see YAHOO.util.Storage.key
1193
		 */
1194
		_key: function(index) {
1195
			return StorageEngineSWF.superclass._key.call(this, index).replace(RX_STORAGE_PREFIX, '');
1196
		},
1197
 
1198
		/*
1199
		 * Implementation to remove an item from the storage engine.
1200
		 * @see YAHOO.util.Storage._removeItem
1201
		 */
1202
		_removeItem: function(sKey) {
1203
			Y.log("removing SWF key: " + sKey);
1204
			var sLocationKey = _getKey(this, sKey);
1205
			StorageEngineSWF.superclass._removeItem.call(this, sLocationKey);
1206
			_driver.callSWF("removeItem", [sLocationKey]);
1207
		},
1208
 
1209
		/*
1210
		 * Implementation to remove an item from the storage engine.
1211
		 * @see YAHOO.util.Storage._setItem
1212
		 */
1213
		_setItem: function(sKey, oData) {
1214
			var sLocationKey = _getKey(this, sKey), swfNode;
1215
 
1216
			if (_driver.callSWF("setItem", [sLocationKey, oData])) {
1217
				this._addKey(sLocationKey);
1218
				return true;
1219
			}
1220
			else {
1221
                /*
1222
                    note:
1223
                        right if the FLASH SLO size needs to be adjusted, then this request and all future requests fail
1224
                        should we queue these up and poll for when there is enough space?
1225
                 */
1226
				swfNode = Dom.get(_driver._id);
1227
				if (MINIMUM_WIDTH > Dom.getStyle(swfNode, 'width').replace(/\D+/g, '')) {Dom.setStyle(swfNode, 'width', MINIMUM_WIDTH + 'px');}
1228
				if (MINIMUM_HEIGHT > Dom.getStyle(swfNode, 'height').replace(/\D+/g, '')) {Dom.setStyle(swfNode, 'height', MINIMUM_HEIGHT + 'px');}
1229
				Y.log("attempting to show settings. are dimensions adequate? " + _driver.callSWF("hasAdequateDimensions"));
1230
				return _driver.callSWF("displaySettings", []);
1231
			}
1232
		}
1233
	});
1234
 
1235
	StorageEngineSWF.SWFURL = "swfstore.swf";
1236
	StorageEngineSWF.ENGINE_NAME = 'swf';
1237
 
1238
    StorageEngineSWF.isAvailable = function() {
1239
		return (6 <= Y.env.ua.flash && Y.widget.SWF);
1240
	};
1241
 
1242
    StorageManager.register(StorageEngineSWF);
1243
	Util.StorageEngineSWF = StorageEngineSWF;
1244
}());
1245
YAHOO.register("storage", YAHOO.util.Storage, {version: "2.9.0", build: "2800"});
1246
 
1247
}, '2.9.0' ,{"requires": ["yui2-yahoo", "yui2-event", "yui2-cookie"], "optional": ["yui2-dom", "yui2-element", "yui2-swf", "yui2-swfstore"]});