2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
8 * The Storage module manages client-side data storage.
21 _logOverwriteError = function(fxName) {
22 Y.log('Exception in YAHOO.util.Storage.?? - must be extended by a storage engine'.replace('??', fxName).replace('??', this.getName ? this.getName() : 'Unknown'), 'error');
26 * The Storage class is an HTML 5 storage API clone, used to wrap individual storage implementations with a common API.
28 * @namespace YAHOO.util
30 * @param location {String} Required. The storage location.
31 * @parm name {String} Required. The engine name.
32 * @param conf {Object} Required. A configuration object.
34 YU.Storage = function(location, name, conf) {
36 Y.env._id_counter += 1;
38 // protected variables
39 that._cfg = YL.isObject(conf) ? conf : {};
40 that._location = location;
45 that.createEvent(that.CE_READY, {scope: that});
46 that.createEvent(that.CE_CHANGE, {scope: that});
48 that.subscribe(that.CE_READY, function() {
53 YU.Storage.prototype = {
56 * The event name for when the storage item is ready.
61 CE_READY: 'YUIStorageReady',
64 * The event name for when the storage item has changed.
69 CE_CHANGE: 'YUIStorageChange',
72 * The delimiter uesed between the data type and the data.
80 * The configuration of the engine.
88 * The name of this engine.
96 * The location for this instance.
104 * The current length of the keys.
112 * This engine singleton has been initialized already.
120 * Clears any existing key/value pairs.
130 * Fetches the data stored and the provided key.
132 * @param key {String} Required. The key used to reference this value (DOMString in HTML 5 spec).
133 * @return {String|NULL} The value stored at the provided key (DOMString in HTML 5 spec).
136 getItem: function(key) {
137 Y.log("Fetching item at " + key);
138 var item = this._getItem(key);
139 return YL.isValue(item) ? this._getValue(item) : null; // required by HTML 5 spec
143 * Fetches the storage object's name; should be overwritten by storage engine.
145 * @return {String} The name of the data storage object.
148 getName: function() {return this._name;},
151 * Tests if the key has been set (not in HTML 5 spec); should be overwritten by storage engine.
153 * @param key {String} Required. The key to search for.
154 * @return {Boolean} True when key has been set.
157 hasKey: function(key) {
158 return YL.isString(key) && this._hasKey(key);
162 * Retrieve the key stored at the provided index; should be overwritten by storage engine.
164 * @param index {Number} Required. The index to retrieve (unsigned long in HTML 5 spec).
165 * @return {String} Required. The key at the provided index (DOMString in HTML 5 spec).
168 key: function(index) {
169 Y.log("Fetching key at " + index);
171 if (YL.isNumber(index) && -1 < index && this.length > index) {
172 var value = this._key(index);
173 if (value) {return value;}
176 // this is thrown according to the HTML5 spec
177 throw('INDEX_SIZE_ERR - Storage.setItem - The provided index (' + index + ') is not available');
181 * Remove an item from the data storage.
183 * @param key {String} Required. The key to remove (DOMString in HTML 5 spec).
186 removeItem: function(key) {
187 Y.log("removing " + key);
189 if (this.hasKey(key)) {
190 var oldValue = this._getItem(key);
191 if (! oldValue) {oldValue = null;}
192 this._removeItem(key);
193 this.fireEvent(this.CE_CHANGE, new YU.StorageEvent(this, key, oldValue, null, YU.StorageEvent.TYPE_REMOVE_ITEM));
196 // HTML 5 spec says to do nothing
201 * Adds an item to the data storage.
203 * @param key {String} Required. The key used to reference this value (DOMString in HTML 5 spec).
204 * @param data {Object} Required. The data to store at key (DOMString in HTML 5 spec).
206 * @throws QUOTA_EXCEEDED_ERROR
208 setItem: function(key, data) {
209 Y.log("SETTING " + data + " to " + key);
211 if (YL.isString(key)) {
212 var eventType = this.hasKey(key) ? YU.StorageEvent.TYPE_UPDATE_ITEM : YU.StorageEvent.TYPE_ADD_ITEM,
213 oldValue = this._getItem(key);
214 if (! oldValue) {oldValue = null;}
216 if (this._setItem(key, this._createValue(data))) {
217 this.fireEvent(this.CE_CHANGE, new YU.StorageEvent(this, key, oldValue, data, eventType));
220 // this is thrown according to the HTML5 spec
221 throw('QUOTA_EXCEEDED_ERROR - Storage.setItem - The choosen storage method (' +
222 this.getName() + ') has exceeded capacity');
226 // HTML 5 spec says to do nothing
231 * Implementation of the clear login; should be overwritten by storage engine.
236 _logOverwriteError('_clear');
241 * Converts the object into a string, with meta data (type), so it can be restored later.
242 * @method _createValue
243 * @param s {Object} Required. An object to store.
246 _createValue: function(s) {
247 var type = (YL.isNull(s) || YL.isUndefined(s)) ? ('' + s) : typeof s;
248 return 'string' === type ? s : type + this.DELIMITER + s;
252 * Implementation of the getItem login; should be overwritten by storage engine.
254 * @param key {String} Required. The key used to reference this value.
255 * @return {String|NULL} The value stored at the provided key.
258 _getItem: function(key) {
259 _logOverwriteError('_getItem');
264 * Converts the stored value into its appropriate type.
266 * @param s {String} Required. The stored value.
269 _getValue: function(s) {
270 var a = s ? s.split(this.DELIMITER) : [];
271 if (1 == a.length) {return s;}
274 case 'boolean': return 'true' === a[1];
275 case 'number': return parseFloat(a[1]);
276 case 'null': return null;
277 default: return a[1];
282 * Implementation of the key logic; should be overwritten by storage engine.
284 * @param index {Number} Required. The index to retrieve (unsigned long in HTML 5 spec).
285 * @return {String|NULL} Required. The key at the provided index (DOMString in HTML 5 spec).
288 _key: function(index) {
289 _logOverwriteError('_key');
294 * Implementation to fetch evaluate the existence of a key.
295 * @see YAHOO.util.Storage._hasKey
297 _hasKey: function(key) {
298 return null !== this._getItem(key);
302 * Implementation of the removeItem login; should be overwritten by storage engine.
303 * @method _removeItem
304 * @param key {String} Required. The key to remove.
307 _removeItem: function(key) {
308 _logOverwriteError('_removeItem');
313 * Implementation of the setItem login; should be overwritten by storage engine.
315 * @param key {String} Required. The key used to reference this value.
316 * @param data {Object} Required. The data to storage at key.
317 * @return {Boolean} True when successful, false when size QUOTA exceeded.
320 _setItem: function(key, data) {
321 _logOverwriteError('_setItem');
326 YL.augmentProto(YU.Storage, YU.EventProvider);
331 * The StorageManager class is a singleton that registers DataStorage objects and returns instances of those objects.
332 * @class StorageManager
333 * @namespace YAHOO.util
337 // internal shorthand
342 _locationEngineMap = {}, // cached engines
343 _registeredEngineSet = [], // set of available engines
344 _registeredEngineMap = {}, // map of available engines
347 * Fetches a storage constructor if it is available, otherwise returns NULL.
349 * @param klass {Function} Required. The storage constructor to test.
350 * @return {Function} An available storage constructor or NULL.
353 _getClass = function(klass) {
354 return (klass && klass.isAvailable()) ? klass : null;
358 * Fetches the storage engine from the cache, or creates and caches it.
359 * @method _getStorageEngine
360 * @param location {String} Required. The location to store.
361 * @param klass {Function} Required. A pointer to the engineType Class.
362 * @param conf {Object} Optional. Additional configuration for the data source engine.
365 _getStorageEngine = function(location, klass, conf) {
366 var engine = _locationEngineMap[location + klass.ENGINE_NAME];
369 engine = new klass(location, conf);
370 _locationEngineMap[location + klass.ENGINE_NAME] = engine;
377 * Ensures that the location is valid before returning it or a default value.
378 * @method _getValidLocation
379 * @param location {String} Required. The location to evaluate.
382 _getValidLocation = function(location) {
384 case Y.StorageManager.LOCATION_LOCAL:
385 case Y.StorageManager.LOCATION_SESSION:
388 default: return Y.StorageManager.LOCATION_SESSION;
396 * The storage location - session; data cleared at the end of a user's session.
397 * @property LOCATION_SESSION
401 LOCATION_SESSION: 'sessionStorage',
404 * The storage location - local; data cleared on demand.
405 * @property LOCATION_LOCAL
409 LOCATION_LOCAL: 'localStorage',
412 * Fetches the desired engine type or first available engine type.
414 * @param engineType {String} Optional. The engine type, see engines.
415 * @param location {String} Optional. The storage location - LOCATION_SESSION & LOCATION_LOCAL; default is LOCAL.
416 * @param conf {Object} Optional. Additional configuration for the getting the storage engine.
418 * engine: {Object} configuration parameters for the desired engine
419 * order: {Array} an array of storage engine names; the desired order to try engines}
423 get: function(engineType, location, conf) {
424 var _cfg = YL.isObject(conf) ? conf : {},
425 klass = _getClass(_registeredEngineMap[engineType]);
427 if (! klass && ! _cfg.force) {
431 j = _cfg.order.length;
433 for (i = 0; i < j && ! klass; i += 1) {
434 klass = _getClass(_cfg.order[i]);
439 j = _registeredEngineSet.length;
441 for (i = 0; i < j && ! klass; i += 1) {
442 klass = _getClass(_registeredEngineSet[i]);
448 return _getStorageEngine(_getValidLocation(location), klass, _cfg.engine);
451 throw('YAHOO.util.StorageManager.get - No engine available, please include an engine before calling this function.');
455 * Estimates the size of the string using 1 byte for each alpha-numeric character and 3 for each non-alpha-numeric character.
456 * @method getByteSize
457 * @param s {String} Required. The string to evaulate.
458 * @return {Number} The estimated string size.
461 getByteSize: function(s) {
462 return encodeURIComponent('' + s).length;
466 * Registers a engineType Class with the StorageManager singleton; first in is the first out.
468 * @param engineConstructor {Function} Required. The engine constructor function, see engines.
469 * @return {Boolean} When successfully registered.
472 register: function(engineConstructor) {
473 if (YL.isFunction(engineConstructor) && YL.isFunction(engineConstructor.isAvailable) && YL.isString(engineConstructor.ENGINE_NAME)) {
474 _registeredEngineMap[engineConstructor.ENGINE_NAME] = engineConstructor;
475 _registeredEngineSet.push(engineConstructor);
483 YAHOO.register("StorageManager", Y.SWFStore, {version: "2.8.0r4", build: "2449"});
488 * The StorageEvent class manages the storage events by emulating the HTML 5 implementation.
489 * @namespace YAHOO.util
490 * @class StorageEvent
492 * @param storageArea {Object} Required. The Storage object that was affected.
493 * @param key {String} Required. The key being changed; DOMString in HTML 5 spec.
494 * @param oldValue {String} Required. The old value of the key being changed; DOMString in HTML 5 spec.
495 * @param newValue {String} Required. The new value of the key being changed; DOMString in HTML 5 spec.
496 * @param type {String} Required. The storage event type.
498 YAHOO.util.StorageEvent = function(storageArea, key, oldValue, newValue, type) {
500 this.oldValue = oldValue;
501 this.newValue = newValue;
502 this.url = window.location.href;
503 this.window = window; // todo: think about the CAJA and innocent code
504 this.storageArea = storageArea;
508 YAHOO.lang.augmentObject(YAHOO.util.StorageEvent, {
509 TYPE_ADD_ITEM: 'addItem',
510 TYPE_REMOVE_ITEM: 'removeItem',
511 TYPE_UPDATE_ITEM: 'updateItem'
514 YAHOO.util.StorageEvent.prototype = {
517 * The 'key' attribute represents the key being changed.
526 * The 'newValue' attribute represents the new value of the key being changed.
535 * The 'oldValue' attribute represents the old value of the key being changed.
544 * The 'source' attribute represents the WindowProxy object of the browsing context of the document whose key changed.
553 * The 'storageArea' attribute represents the Storage object that was affected.
554 * @property storageArea
562 * The 'type' attribute represents the Storage event type.
571 * The 'url' attribute represents the address of the document whose key changed.
586 * The StorageEngineKeyed class implements the interface necessary for managing keys.
587 * @namespace YAHOO.util
588 * @class StorageEngineKeyed
590 * @extend YAHOO.util.Storage
592 Y.StorageEngineKeyed = function() {
593 Y.StorageEngineKeyed.superclass.constructor.apply(this, arguments);
598 YL.extend(Y.StorageEngineKeyed, Y.Storage, {
601 * A collection of keys applicable to the current location. This should never be edited by the developer.
609 * A map of keys to their applicable position in keys array. This should never be edited by the developer.
617 * Adds the key to the set.
619 * @param key {String} Required. The key to evaluate.
622 _addKey: function(key) {
623 this._keyMap[key] = this.length;
624 this._keys.push(key);
625 this.length = this._keys.length;
629 * Evaluates if a key exists in the keys array; indexOf does not work in all flavors of IE.
630 * @method _indexOfKey
631 * @param key {String} Required. The key to evaluate.
634 _indexOfKey: function(key) {
635 var i = this._keyMap[key];
636 return undefined === i ? -1 : i;
640 * Removes a key from the keys array.
642 * @param key {String} Required. The key to remove.
645 _removeKey: function(key) {
646 var j = this._indexOfKey(key),
647 rest = this._keys.slice(j + 1);
649 delete this._keyMap[key];
651 for (var k in this._keyMap) {
652 if (j < this._keyMap[k]) {
653 this._keyMap[k] -= 1;
657 this._keys.length = j;
658 this._keys = this._keys.concat(rest);
659 this.length = this._keys.length;
665 * - 5MB in FF and Safari, 10MB in IE 8
666 * - only FF 3.5 recovers session storage after a browser crash
669 * - how can we not use cookies to handle session
672 // internal shorthand
677 * Required for IE 8 to make synchronous.
679 _beginTransaction = function(engine) {
680 if (engine.begin) {engine.begin();}
684 * Required for IE 8 to make synchronous.
686 _commitTransaction = function(engine) {
687 if (engine.commit) {engine.commit();}
691 * The StorageEngineHTML5 class implements the HTML5 storage engine.
692 * @namespace YAHOO.util
693 * @class StorageEngineHTML5
695 * @extend YAHOO.util.Storage
696 * @param location {String} Required. The storage location.
697 * @param conf {Object} Required. A configuration object.
699 Y.StorageEngineHTML5 = function(location, conf) {
701 Y.StorageEngineHTML5.superclass.constructor.call(_this, location, Y.StorageEngineHTML5.ENGINE_NAME, conf);// not set, are cookies available
702 _this._engine = window[location];
703 _this.length = _this._engine.length;
704 YL.later(250, _this, function() { // temporary solution so that CE_READY can be subscribed to after this object is created
705 _this.fireEvent(_this.CE_READY);
709 YAHOO.lang.extend(Y.StorageEngineHTML5, Y.Storage, {
714 * Implementation to clear the values from the storage engine.
715 * @see YAHOO.util.Storage._clear
719 if (_this._engine.clear) {
720 _this._engine.clear();
722 // for FF 3, fixed in FF 3.5
724 for (var i = _this.length, key; 0 <= i; i -= 1) {
726 _this._removeItem(key);
732 * Implementation to fetch an item from the storage engine.
733 * @see YAHOO.util.Storage._getItem
735 _getItem: function(key) {
736 var o = this._engine.getItem(key);
737 return YL.isObject(o) ? o.value : o; // for FF 3, fixed in FF 3.5
741 * Implementation to fetch a key from the storage engine.
742 * @see YAHOO.util.Storage._key
744 _key: function(index) {return this._engine.key(index);},
747 * Implementation to remove an item from the storage engine.
748 * @see YAHOO.util.Storage._removeItem
750 _removeItem: function(key) {
752 _beginTransaction(_this._engine);
753 _this._engine.removeItem(key);
754 _commitTransaction(_this._engine);
755 _this.length = _this._engine.length;
759 * Implementation to remove an item from the storage engine.
760 * @see YAHOO.util.Storage._setItem
762 _setItem: function(key, value) {
766 _beginTransaction(_this._engine);
767 _this._engine.setItem(key, value);
768 _commitTransaction(_this._engine);
769 _this.length = _this._engine.length;
778 Y.StorageEngineHTML5.ENGINE_NAME = 'html5';
779 Y.StorageEngineHTML5.isAvailable = function() {
780 return window.localStorage;
782 Y.StorageManager.register(Y.StorageEngineHTML5);
786 * - SQLite limitations - http://www.sqlite.org/limits.html
787 * - DB Best Practices - http://code.google.com/apis/gears/gears_faq.html#bestPracticeDB
788 * - the user must approve before gears can be used
789 * - each SQL query has a limited number of characters (9948 bytes), data will need to be spread across rows
790 * - no query should insert or update more than 9948 bytes of data in a single statement or GEARs will throw:
791 * [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]
794 * - we may want to implement additional functions for the gears only implementation
795 * - how can we not use cookies to handle session location
798 // internal shorthand
801 _SQL_STMT_LIMIT = 9948,
802 _TABLE_NAME = 'YUIStorageEngine',
807 eURI = encodeURIComponent,
808 dURI = decodeURIComponent;
811 * The StorageEngineGears class implements the Google Gears storage engine.
812 * @namespace YAHOO.util
813 * @class StorageEngineGears
815 * @extend YAHOO.util.Storage
816 * @param location {String} Required. The storage location.
817 * @param conf {Object} Required. A configuration object.
819 Y.StorageEngineGears = function(location, conf) {
821 Y.StorageEngineGears.superclass.constructor.call(_this, location, Y.StorageEngineGears.ENGINE_NAME, conf);
824 // create the database
825 _engine = google.gears.factory.create(Y.StorageEngineGears.GEARS);
826 _engine.open(window.location.host + '-' + Y.StorageEngineGears.DATABASE);
827 _engine.execute('CREATE TABLE IF NOT EXISTS ' + _TABLE_NAME + ' (key TEXT, location TEXT, value TEXT)');
830 var isSessionStorage = Y.StorageManager.LOCATION_SESSION === _this._location,
831 sessionKey = Y.Cookie.get('sessionKey' + Y.StorageEngineGears.ENGINE_NAME);
834 _engine.execute('BEGIN');
835 _engine.execute('DELETE FROM ' + _TABLE_NAME + ' WHERE location="' + eURI(Y.StorageManager.LOCATION_SESSION) + '"');
836 _engine.execute('COMMIT');
839 var rs = _engine.execute('SELECT key FROM ' + _TABLE_NAME + ' WHERE location="' + eURI(_this._location) + '"'),
843 // iterate on the rows and map the keys
844 while (rs.isValidRow()) {
845 var fld = dURI(rs.field(0));
859 // this is session storage, ensure that the session key is set
860 if (isSessionStorage) {
861 Y.Cookie.set('sessionKey' + Y.StorageEngineGears.ENGINE_NAME, true);
864 _this.length = _this._keys.length;
865 YL.later(250, _this, function() { // temporary solution so that CE_READY can be subscribed to after this object is created
866 _this.fireEvent(_this.CE_READY);
870 YL.extend(Y.StorageEngineGears, Y.StorageEngineKeyed, {
873 * Implementation to clear the values from the storage engine.
874 * @see YAHOO.util.Storage._clear
877 _engine.execute('BEGIN');
878 _engine.execute('DELETE FROM ' + _TABLE_NAME + ' WHERE location="' + eURI(this._location) + '"');
879 _engine.execute('COMMIT');
885 * Implementation to fetch an item from the storage engine.
886 * @see YAHOO.util.Storage._getItem
888 _getItem: function(key) {
889 var rs = _engine.execute('SELECT value FROM ' + _TABLE_NAME + ' WHERE key="' + eURI(key) + '" AND location="' + eURI(this._location) + '"'),
893 while (rs.isValidRow()) {
894 var temp = rs.field(0);
895 value += rs.field(0);
903 return value ? dURI(value) : null;
907 * Implementation to fetch a key from the storage engine.
908 * @see YAHOO.util.Storage.key
910 _key: function(index) {return this._keys[index];},
913 * Implementation to remove an item from the storage engine.
914 * @see YAHOO.util.Storage._removeItem
916 _removeItem: function(key) {
917 _engine.execute('BEGIN');
918 _engine.execute('DELETE FROM ' + _TABLE_NAME + ' WHERE key="' + eURI(key) + '" AND location="' + eURI(this._location) + '"');
919 _engine.execute('COMMIT');
920 this._removeKey(key);
924 * Implementation to remove an item from the storage engine.
925 * @see YAHOO.util.Storage._setItem
927 _setItem: function(key, data) {
929 if (! this.hasKey(key)) {
933 var _key = eURI(key),
934 _location = eURI(this._location),
937 _len = _SQL_STMT_LIMIT - (_key + _location).length;
939 // the length of the value exceeds the available space
940 if (_len < _value.length) {
941 for (var i = 0, j = _value.length; i < j; i += _len) {
942 _values.push(_value.substr(i, _len));
946 _values.push(_value);
949 // Google recommends using INSERT instead of update, because it is faster
950 _engine.execute('BEGIN');
951 _engine.execute('DELETE FROM ' + _TABLE_NAME + ' WHERE key="' + eURI(key) + '" AND location="' + eURI(this._location) + '"');
952 for (var m = 0, n = _values.length; m < n; m += 1) {
953 _engine.execute('INSERT INTO ' + _TABLE_NAME + ' VALUES ("' + _key + '", "' + _location + '", "' + _values[m] + '")');
955 _engine.execute('COMMIT');
961 // releases the engine when the page unloads
962 Y.Event.on('unload', function() {
963 if (_engine) {_engine.close();}
965 Y.StorageEngineGears.ENGINE_NAME = 'gears';
966 Y.StorageEngineGears.GEARS = 'beta.database';
967 Y.StorageEngineGears.DATABASE = 'yui.database';
968 Y.StorageEngineGears.isAvailable = function() {
969 if (window.google && window.google.gears) {
971 // this will throw an exception if the user denies gears
972 google.gears.factory.create(Y.StorageEngineGears.GEARS);
976 // no need to do anything
982 Y.StorageManager.register(Y.StorageEngineGears);
986 * - only 100,000 bytes of data may be stored this way
987 * - data is publicly available on user machine
990 * - data can be shared across browsers
991 * - how can we not use cookies to handle session location
994 // internal shorthand
1000 * The minimum width required to be able to display the settings panel within the SWF.
1002 MINIMUM_WIDTH = 215,
1005 * The minimum height required to be able to display the settings panel within the SWF.
1007 MINIMUM_HEIGHT = 138,
1013 * Creates a location bound key.
1015 _getKey = function(that, key) {
1016 return that._location + that.DELIMITER + key;
1020 * Initializes the engine, if it isn't already initialized.
1022 _initEngine = function(cfg) {
1024 if (! YL.isString(cfg.swfURL)) {cfg.swfURL = Y.StorageEngineSWF.SWFURL;}
1025 if (! cfg.containerID) {
1026 var bd = document.getElementsByTagName('body')[0],
1027 container = bd.appendChild(document.createElement('div'));
1028 cfg.containerID = YD.generateId(container);
1031 if (! cfg.attributes) {cfg.attributes = {};}
1032 if (! cfg.attributes.flashVars) {cfg.attributes.flashVars = {};}
1033 cfg.attributes.flashVars.useCompression = 'true';
1034 cfg.attributes.version = 9.115;
1035 _engine = new YAHOO.widget.SWF(cfg.containerID, cfg.swfURL, cfg.attributes);
1040 * The StorageEngineSWF class implements the SWF storage engine.
1041 * @namespace YAHOO.util
1042 * @class StorageEngineSWF
1043 * @uses YAHOO.widget.SWF
1045 * @extend YAHOO.util.Storage
1046 * @param location {String} Required. The storage location.
1047 * @param conf {Object} Required. A configuration object.
1049 Y.StorageEngineSWF = function(location, conf) {
1051 Y.StorageEngineSWF.superclass.constructor.call(_this, location, Y.StorageEngineSWF.ENGINE_NAME, conf);
1053 _initEngine(_this._cfg);
1055 // evaluates when the SWF is loaded
1056 _engine.unsubscribe('contentReady'); // prevents local and session content ready callbacks from firing, when switching between context
1057 _engine.addListener("contentReady", function() {
1058 _this._swf = _engine._swf;
1059 _engine.initialized = true;
1061 var isSessionStorage = Y.StorageManager.LOCATION_SESSION === _this._location,
1062 sessionKey = Y.Cookie.get('sessionKey' + Y.StorageEngineSWF.ENGINE_NAME);
1064 for (var i = _engine.callSWF("getLength", []) - 1; 0 <= i; i -= 1) {
1065 var key = _engine.callSWF("getNameAt", [i]),
1066 isKeySessionStorage = -1 < key.indexOf(Y.StorageManager.LOCATION_SESSION + _this.DELIMITER);
1068 // this is session storage, but the session key is not set, so remove item
1069 if (isSessionStorage && ! sessionKey) {
1070 _engine.callSWF("removeItem", [key]);
1072 // the key matches the storage type, add to key collection
1073 else if (isSessionStorage === isKeySessionStorage) {
1078 // this is session storage, ensure that the session key is set
1079 if (isSessionStorage) {
1080 Y.Cookie.set('sessionKey' + Y.StorageEngineSWF.ENGINE_NAME, true);
1083 _this.length = _this._keys.length;
1084 _this.fireEvent(_this.CE_READY);
1087 // required for pages with both a session and local storage
1088 if (_engine.initialized) {_engine.fireEvent('contentReady');}
1091 YL.extend(Y.StorageEngineSWF, Y.StorageEngineKeyed, {
1093 * The underlying SWF of the engine, exposed so developers can modify the adapter behavior.
1101 * Implementation to clear the values from the storage engine.
1102 * @see YAHOO.util.Storage._clear
1104 _clear: function() {
1105 for (var i = this._keys.length - 1; 0 <= i; i -= 1) {
1106 var key = this._keys[i];
1107 _engine.callSWF("removeItem", [key]);
1115 * Implementation to fetch an item from the storage engine.
1116 * @see YAHOO.util.Storage._getItem
1118 _getItem: function(key) {
1119 var _key = _getKey(this, key);
1120 return _engine.callSWF("getValueOf", [_key]);
1124 * Implementation to fetch a key from the storage engine.
1125 * @see YAHOO.util.Storage.key
1127 _key: function(index) {
1128 return (this._keys[index] || '').replace(/^.*?__/, '');
1132 * Implementation to remove an item from the storage engine.
1133 * @see YAHOO.util.Storage._removeItem
1135 _removeItem: function(key) {
1136 var _key = _getKey(this, key);
1137 _engine.callSWF("removeItem", [_key]);
1138 this._removeKey(_key);
1142 * Implementation to remove an item from the storage engine.
1143 * @see YAHOO.util.Storage._setItem
1145 _setItem: function(key, data) {
1146 var _key = _getKey(this, key), swfNode;
1148 // setting the value returns false if the value didn't change,
1149 // so I changed this to clear the key if it exists so that the
1150 // fork below works.
1151 if (_engine.callSWF("getValueOf", [_key])) {
1152 this._removeItem(key);
1157 if (_engine.callSWF("setItem", [_key, data])) {
1161 // @TODO we should not assume that a false return means that
1162 // the quota has been exceeded. this dialog should only be
1163 // displayed if the quotaExceededError event fired.
1164 swfNode = YD.get(_engine._id);
1165 if (MINIMUM_WIDTH > YD.getStyle(swfNode, 'width').replace(/\D+/g, '')) {
1166 YD.setStyle(swfNode, 'width', MINIMUM_WIDTH + 'px');
1168 if (MINIMUM_HEIGHT > YD.getStyle(swfNode, 'height').replace(/\D+/g, '')) {
1169 YD.setStyle(swfNode, 'height', MINIMUM_HEIGHT + 'px');
1171 return _engine.callSWF("displaySettings", []);
1176 Y.StorageEngineSWF.SWFURL = "swfstore.swf";
1177 Y.StorageEngineSWF.ENGINE_NAME = 'swf';
1178 Y.StorageEngineSWF.isAvailable = function() {
1179 return (6 <= YAHOO.env.ua.flash && YAHOO.widget.SWF);
1181 Y.StorageManager.register(Y.StorageEngineSWF);
1183 YAHOO.register("storage", YAHOO.util.Storage, {version: "2.8.0r4", build: "2449"});