1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186 |
- /*
- Copyright (c) 2009, Yahoo! Inc. All rights reserved.
- Code licensed under the BSD License:
- http://developer.yahoo.net/yui/license.txt
- version: 2.8.0r4
- */
- /**
- * The Storage module manages client-side data storage.
- * @module Storage
- */
- (function() {
- // internal shorthand
- var Y = YAHOO,
- YU = Y.util,
- YL = Y.lang,
- _logOverwriteError;
- if (! YU.Storage) {
- _logOverwriteError = function(fxName) {
- Y.log('Exception in YAHOO.util.Storage.?? - must be extended by a storage engine'.replace('??', fxName).replace('??', this.getName ? this.getName() : 'Unknown'), 'error');
- };
- /**
- * The Storage class is an HTML 5 storage API clone, used to wrap individual storage implementations with a common API.
- * @class Storage
- * @namespace YAHOO.util
- * @constructor
- * @param location {String} Required. The storage location.
- * @parm name {String} Required. The engine name.
- * @param conf {Object} Required. A configuration object.
- */
- YU.Storage = function(location, name, conf) {
- var that = this;
- Y.env._id_counter += 1;
- // protected variables
- that._cfg = YL.isObject(conf) ? conf : {};
- that._location = location;
- that._name = name;
- that.isReady = false;
- // public variables
- that.createEvent(that.CE_READY, {scope: that});
- that.createEvent(that.CE_CHANGE, {scope: that});
-
- that.subscribe(that.CE_READY, function() {
- that.isReady = true;
- });
- };
- YU.Storage.prototype = {
- /**
- * The event name for when the storage item is ready.
- * @property CE_READY
- * @type {String}
- * @public
- */
- CE_READY: 'YUIStorageReady',
- /**
- * The event name for when the storage item has changed.
- * @property CE_CHANGE
- * @type {String}
- * @public
- */
- CE_CHANGE: 'YUIStorageChange',
- /**
- * The delimiter uesed between the data type and the data.
- * @property DELIMITER
- * @type {String}
- * @public
- */
- DELIMITER: '__',
- /**
- * The configuration of the engine.
- * @property _cfg
- * @type {Object}
- * @protected
- */
- _cfg: '',
- /**
- * The name of this engine.
- * @property _name
- * @type {String}
- * @protected
- */
- _name: '',
- /**
- * The location for this instance.
- * @property _location
- * @type {String}
- * @protected
- */
- _location: '',
- /**
- * The current length of the keys.
- * @property length
- * @type {Number}
- * @public
- */
- length: 0,
- /**
- * This engine singleton has been initialized already.
- * @property isReady
- * @type {String}
- * @protected
- */
- isReady: false,
- /**
- * Clears any existing key/value pairs.
- * @method clear
- * @public
- */
- clear: function() {
- this._clear();
- this.length = 0;
- },
- /**
- * Fetches the data stored and the provided key.
- * @method getItem
- * @param key {String} Required. The key used to reference this value (DOMString in HTML 5 spec).
- * @return {String|NULL} The value stored at the provided key (DOMString in HTML 5 spec).
- * @public
- */
- getItem: function(key) {
- Y.log("Fetching item at " + key);
- var item = this._getItem(key);
- return YL.isValue(item) ? this._getValue(item) : null; // required by HTML 5 spec
- },
- /**
- * Fetches the storage object's name; should be overwritten by storage engine.
- * @method getName
- * @return {String} The name of the data storage object.
- * @public
- */
- getName: function() {return this._name;},
- /**
- * Tests if the key has been set (not in HTML 5 spec); should be overwritten by storage engine.
- * @method hasKey
- * @param key {String} Required. The key to search for.
- * @return {Boolean} True when key has been set.
- * @public
- */
- hasKey: function(key) {
- return YL.isString(key) && this._hasKey(key);
- },
- /**
- * Retrieve the key stored at the provided index; should be overwritten by storage engine.
- * @method key
- * @param index {Number} Required. The index to retrieve (unsigned long in HTML 5 spec).
- * @return {String} Required. The key at the provided index (DOMString in HTML 5 spec).
- * @public
- */
- key: function(index) {
- Y.log("Fetching key at " + index);
- if (YL.isNumber(index) && -1 < index && this.length > index) {
- var value = this._key(index);
- if (value) {return value;}
- }
- // this is thrown according to the HTML5 spec
- throw('INDEX_SIZE_ERR - Storage.setItem - The provided index (' + index + ') is not available');
- },
- /**
- * Remove an item from the data storage.
- * @method setItem
- * @param key {String} Required. The key to remove (DOMString in HTML 5 spec).
- * @public
- */
- removeItem: function(key) {
- Y.log("removing " + key);
-
- if (this.hasKey(key)) {
- var oldValue = this._getItem(key);
- if (! oldValue) {oldValue = null;}
- this._removeItem(key);
- this.fireEvent(this.CE_CHANGE, new YU.StorageEvent(this, key, oldValue, null, YU.StorageEvent.TYPE_REMOVE_ITEM));
- }
- else {
- // HTML 5 spec says to do nothing
- }
- },
- /**
- * Adds an item to the data storage.
- * @method setItem
- * @param key {String} Required. The key used to reference this value (DOMString in HTML 5 spec).
- * @param data {Object} Required. The data to store at key (DOMString in HTML 5 spec).
- * @public
- * @throws QUOTA_EXCEEDED_ERROR
- */
- setItem: function(key, data) {
- Y.log("SETTING " + data + " to " + key);
-
- if (YL.isString(key)) {
- var eventType = this.hasKey(key) ? YU.StorageEvent.TYPE_UPDATE_ITEM : YU.StorageEvent.TYPE_ADD_ITEM,
- oldValue = this._getItem(key);
- if (! oldValue) {oldValue = null;}
- if (this._setItem(key, this._createValue(data))) {
- this.fireEvent(this.CE_CHANGE, new YU.StorageEvent(this, key, oldValue, data, eventType));
- }
- else {
- // this is thrown according to the HTML5 spec
- throw('QUOTA_EXCEEDED_ERROR - Storage.setItem - The choosen storage method (' +
- this.getName() + ') has exceeded capacity');
- }
- }
- else {
- // HTML 5 spec says to do nothing
- }
- },
- /**
- * Implementation of the clear login; should be overwritten by storage engine.
- * @method _clear
- * @protected
- */
- _clear: function() {
- _logOverwriteError('_clear');
- return '';
- },
- /**
- * Converts the object into a string, with meta data (type), so it can be restored later.
- * @method _createValue
- * @param s {Object} Required. An object to store.
- * @protected
- */
- _createValue: function(s) {
- var type = (YL.isNull(s) || YL.isUndefined(s)) ? ('' + s) : typeof s;
- return 'string' === type ? s : type + this.DELIMITER + s;
- },
- /**
- * Implementation of the getItem login; should be overwritten by storage engine.
- * @method _getItem
- * @param key {String} Required. The key used to reference this value.
- * @return {String|NULL} The value stored at the provided key.
- * @protected
- */
- _getItem: function(key) {
- _logOverwriteError('_getItem');
- return '';
- },
- /**
- * Converts the stored value into its appropriate type.
- * @method _getValue
- * @param s {String} Required. The stored value.
- * @protected
- */
- _getValue: function(s) {
- var a = s ? s.split(this.DELIMITER) : [];
- if (1 == a.length) {return s;}
- switch (a[0]) {
- case 'boolean': return 'true' === a[1];
- case 'number': return parseFloat(a[1]);
- case 'null': return null;
- default: return a[1];
- }
- },
- /**
- * Implementation of the key logic; should be overwritten by storage engine.
- * @method _key
- * @param index {Number} Required. The index to retrieve (unsigned long in HTML 5 spec).
- * @return {String|NULL} Required. The key at the provided index (DOMString in HTML 5 spec).
- * @protected
- */
- _key: function(index) {
- _logOverwriteError('_key');
- return '';
- },
- /*
- * Implementation to fetch evaluate the existence of a key.
- * @see YAHOO.util.Storage._hasKey
- */
- _hasKey: function(key) {
- return null !== this._getItem(key);
- },
- /**
- * Implementation of the removeItem login; should be overwritten by storage engine.
- * @method _removeItem
- * @param key {String} Required. The key to remove.
- * @protected
- */
- _removeItem: function(key) {
- _logOverwriteError('_removeItem');
- return '';
- },
- /**
- * Implementation of the setItem login; should be overwritten by storage engine.
- * @method _setItem
- * @param key {String} Required. The key used to reference this value.
- * @param data {Object} Required. The data to storage at key.
- * @return {Boolean} True when successful, false when size QUOTA exceeded.
- * @protected
- */
- _setItem: function(key, data) {
- _logOverwriteError('_setItem');
- return '';
- }
- };
- YL.augmentProto(YU.Storage, YU.EventProvider);
- }
- }());
- /**
- * The StorageManager class is a singleton that registers DataStorage objects and returns instances of those objects.
- * @class StorageManager
- * @namespace YAHOO.util
- * @static
- */
- (function() {
- // internal shorthand
- var Y = YAHOO.util,
- YL = YAHOO.lang,
- // private variables
- _locationEngineMap = {}, // cached engines
- _registeredEngineSet = [], // set of available engines
- _registeredEngineMap = {}, // map of available engines
-
- /**
- * Fetches a storage constructor if it is available, otherwise returns NULL.
- * @method _getClass
- * @param klass {Function} Required. The storage constructor to test.
- * @return {Function} An available storage constructor or NULL.
- * @private
- */
- _getClass = function(klass) {
- return (klass && klass.isAvailable()) ? klass : null;
- },
- /**
- * Fetches the storage engine from the cache, or creates and caches it.
- * @method _getStorageEngine
- * @param location {String} Required. The location to store.
- * @param klass {Function} Required. A pointer to the engineType Class.
- * @param conf {Object} Optional. Additional configuration for the data source engine.
- * @private
- */
- _getStorageEngine = function(location, klass, conf) {
- var engine = _locationEngineMap[location + klass.ENGINE_NAME];
- if (! engine) {
- engine = new klass(location, conf);
- _locationEngineMap[location + klass.ENGINE_NAME] = engine;
- }
- return engine;
- },
- /**
- * Ensures that the location is valid before returning it or a default value.
- * @method _getValidLocation
- * @param location {String} Required. The location to evaluate.
- * @private
- */
- _getValidLocation = function(location) {
- switch (location) {
- case Y.StorageManager.LOCATION_LOCAL:
- case Y.StorageManager.LOCATION_SESSION:
- return location;
- default: return Y.StorageManager.LOCATION_SESSION;
- }
- };
- // public namespace
- Y.StorageManager = {
- /**
- * The storage location - session; data cleared at the end of a user's session.
- * @property LOCATION_SESSION
- * @type {String}
- * @static
- */
- LOCATION_SESSION: 'sessionStorage',
- /**
- * The storage location - local; data cleared on demand.
- * @property LOCATION_LOCAL
- * @type {String}
- * @static
- */
- LOCATION_LOCAL: 'localStorage',
- /**
- * Fetches the desired engine type or first available engine type.
- * @method get
- * @param engineType {String} Optional. The engine type, see engines.
- * @param location {String} Optional. The storage location - LOCATION_SESSION & LOCATION_LOCAL; default is LOCAL.
- * @param conf {Object} Optional. Additional configuration for the getting the storage engine.
- * {
- * engine: {Object} configuration parameters for the desired engine
- * order: {Array} an array of storage engine names; the desired order to try engines}
- * }
- * @static
- */
- get: function(engineType, location, conf) {
- var _cfg = YL.isObject(conf) ? conf : {},
- klass = _getClass(_registeredEngineMap[engineType]);
- if (! klass && ! _cfg.force) {
- var i, j;
- if (_cfg.order) {
- j = _cfg.order.length;
- for (i = 0; i < j && ! klass; i += 1) {
- klass = _getClass(_cfg.order[i]);
- }
- }
- if (! klass) {
- j = _registeredEngineSet.length;
- for (i = 0; i < j && ! klass; i += 1) {
- klass = _getClass(_registeredEngineSet[i]);
- }
- }
- }
- if (klass) {
- return _getStorageEngine(_getValidLocation(location), klass, _cfg.engine);
- }
- throw('YAHOO.util.StorageManager.get - No engine available, please include an engine before calling this function.');
- },
- /*
- * Estimates the size of the string using 1 byte for each alpha-numeric character and 3 for each non-alpha-numeric character.
- * @method getByteSize
- * @param s {String} Required. The string to evaulate.
- * @return {Number} The estimated string size.
- * @private
- */
- getByteSize: function(s) {
- return encodeURIComponent('' + s).length;
- },
- /**
- * Registers a engineType Class with the StorageManager singleton; first in is the first out.
- * @method register
- * @param engineConstructor {Function} Required. The engine constructor function, see engines.
- * @return {Boolean} When successfully registered.
- * @static
- */
- register: function(engineConstructor) {
- if (YL.isFunction(engineConstructor) && YL.isFunction(engineConstructor.isAvailable) && YL.isString(engineConstructor.ENGINE_NAME)) {
- _registeredEngineMap[engineConstructor.ENGINE_NAME] = engineConstructor;
- _registeredEngineSet.push(engineConstructor);
- return true;
- }
- return false;
- }
- };
- YAHOO.register("StorageManager", Y.SWFStore, {version: "2.8.0r4", build: "2449"});
- }());
- (function() {
- /**
- * The StorageEvent class manages the storage events by emulating the HTML 5 implementation.
- * @namespace YAHOO.util
- * @class StorageEvent
- * @constructor
- * @param storageArea {Object} Required. The Storage object that was affected.
- * @param key {String} Required. The key being changed; DOMString in HTML 5 spec.
- * @param oldValue {String} Required. The old value of the key being changed; DOMString in HTML 5 spec.
- * @param newValue {String} Required. The new value of the key being changed; DOMString in HTML 5 spec.
- * @param type {String} Required. The storage event type.
- */
- YAHOO.util.StorageEvent = function(storageArea, key, oldValue, newValue, type) {
- this.key = key;
- this.oldValue = oldValue;
- this.newValue = newValue;
- this.url = window.location.href;
- this.window = window; // todo: think about the CAJA and innocent code
- this.storageArea = storageArea;
- this.type = type;
- };
- YAHOO.lang.augmentObject(YAHOO.util.StorageEvent, {
- TYPE_ADD_ITEM: 'addItem',
- TYPE_REMOVE_ITEM: 'removeItem',
- TYPE_UPDATE_ITEM: 'updateItem'
- });
- YAHOO.util.StorageEvent.prototype = {
- /**
- * The 'key' attribute represents the key being changed.
- * @property key
- * @type {String}
- * @static
- * @readonly
- */
- key: null,
- /**
- * The 'newValue' attribute represents the new value of the key being changed.
- * @property newValue
- * @type {String}
- * @static
- * @readonly
- */
- newValue: null,
- /**
- * The 'oldValue' attribute represents the old value of the key being changed.
- * @property oldValue
- * @type {String}
- * @static
- * @readonly
- */
- oldValue: null,
- /**
- * The 'source' attribute represents the WindowProxy object of the browsing context of the document whose key changed.
- * @property source
- * @type {Object}
- * @static
- * @readonly
- */
- source: null,
- /**
- * The 'storageArea' attribute represents the Storage object that was affected.
- * @property storageArea
- * @type {Object}
- * @static
- * @readonly
- */
- storageArea: null,
- /**
- * The 'type' attribute represents the Storage event type.
- * @property type
- * @type {Object}
- * @static
- * @readonly
- */
- type: null,
- /**
- * The 'url' attribute represents the address of the document whose key changed.
- * @property url
- * @type {String}
- * @static
- * @readonly
- */
- url: null
- };
-
- }());
- (function() {
- var Y = YAHOO.util,
- YL = YAHOO.lang;
- /**
- * The StorageEngineKeyed class implements the interface necessary for managing keys.
- * @namespace YAHOO.util
- * @class StorageEngineKeyed
- * @constructor
- * @extend YAHOO.util.Storage
- */
- Y.StorageEngineKeyed = function() {
- Y.StorageEngineKeyed.superclass.constructor.apply(this, arguments);
- this._keys = [];
- this._keyMap = {};
- };
- YL.extend(Y.StorageEngineKeyed, Y.Storage, {
- /**
- * A collection of keys applicable to the current location. This should never be edited by the developer.
- * @property _keys
- * @type {Array}
- * @protected
- */
- _keys: null,
- /**
- * A map of keys to their applicable position in keys array. This should never be edited by the developer.
- * @property _keyMap
- * @type {Object}
- * @protected
- */
- _keyMap: null,
- /**
- * Adds the key to the set.
- * @method _addKey
- * @param key {String} Required. The key to evaluate.
- * @protected
- */
- _addKey: function(key) {
- this._keyMap[key] = this.length;
- this._keys.push(key);
- this.length = this._keys.length;
- },
- /**
- * Evaluates if a key exists in the keys array; indexOf does not work in all flavors of IE.
- * @method _indexOfKey
- * @param key {String} Required. The key to evaluate.
- * @protected
- */
- _indexOfKey: function(key) {
- var i = this._keyMap[key];
- return undefined === i ? -1 : i;
- },
- /**
- * Removes a key from the keys array.
- * @method _removeKey
- * @param key {String} Required. The key to remove.
- * @protected
- */
- _removeKey: function(key) {
- var j = this._indexOfKey(key),
- rest = this._keys.slice(j + 1);
- delete this._keyMap[key];
- for (var k in this._keyMap) {
- if (j < this._keyMap[k]) {
- this._keyMap[k] -= 1;
- }
- }
-
- this._keys.length = j;
- this._keys = this._keys.concat(rest);
- this.length = this._keys.length;
- }
- });
- }());
- /*
- * HTML limitations:
- * - 5MB in FF and Safari, 10MB in IE 8
- * - only FF 3.5 recovers session storage after a browser crash
- *
- * Thoughts:
- * - how can we not use cookies to handle session
- */
- (function() {
- // internal shorthand
- var Y = YAHOO.util,
- YL = YAHOO.lang,
- /*
- * Required for IE 8 to make synchronous.
- */
- _beginTransaction = function(engine) {
- if (engine.begin) {engine.begin();}
- },
- /*
- * Required for IE 8 to make synchronous.
- */
- _commitTransaction = function(engine) {
- if (engine.commit) {engine.commit();}
- };
- /**
- * The StorageEngineHTML5 class implements the HTML5 storage engine.
- * @namespace YAHOO.util
- * @class StorageEngineHTML5
- * @constructor
- * @extend YAHOO.util.Storage
- * @param location {String} Required. The storage location.
- * @param conf {Object} Required. A configuration object.
- */
- Y.StorageEngineHTML5 = function(location, conf) {
- var _this = this;
- Y.StorageEngineHTML5.superclass.constructor.call(_this, location, Y.StorageEngineHTML5.ENGINE_NAME, conf);// not set, are cookies available
- _this._engine = window[location];
- _this.length = _this._engine.length;
- YL.later(250, _this, function() { // temporary solution so that CE_READY can be subscribed to after this object is created
- _this.fireEvent(_this.CE_READY);
- });
- };
- YAHOO.lang.extend(Y.StorageEngineHTML5, Y.Storage, {
- _engine: null,
- /*
- * Implementation to clear the values from the storage engine.
- * @see YAHOO.util.Storage._clear
- */
- _clear: function() {
- var _this = this;
- if (_this._engine.clear) {
- _this._engine.clear();
- }
- // for FF 3, fixed in FF 3.5
- else {
- for (var i = _this.length, key; 0 <= i; i -= 1) {
- key = _this._key(i);
- _this._removeItem(key);
- }
- }
- },
- /*
- * Implementation to fetch an item from the storage engine.
- * @see YAHOO.util.Storage._getItem
- */
- _getItem: function(key) {
- var o = this._engine.getItem(key);
- return YL.isObject(o) ? o.value : o; // for FF 3, fixed in FF 3.5
- },
- /*
- * Implementation to fetch a key from the storage engine.
- * @see YAHOO.util.Storage._key
- */
- _key: function(index) {return this._engine.key(index);},
- /*
- * Implementation to remove an item from the storage engine.
- * @see YAHOO.util.Storage._removeItem
- */
- _removeItem: function(key) {
- var _this = this;
- _beginTransaction(_this._engine);
- _this._engine.removeItem(key);
- _commitTransaction(_this._engine);
- _this.length = _this._engine.length;
- },
- /*
- * Implementation to remove an item from the storage engine.
- * @see YAHOO.util.Storage._setItem
- */
- _setItem: function(key, value) {
- var _this = this;
-
- try {
- _beginTransaction(_this._engine);
- _this._engine.setItem(key, value);
- _commitTransaction(_this._engine);
- _this.length = _this._engine.length;
- return true;
- }
- catch (e) {
- return false;
- }
- }
- }, true);
- Y.StorageEngineHTML5.ENGINE_NAME = 'html5';
- Y.StorageEngineHTML5.isAvailable = function() {
- return window.localStorage;
- };
- Y.StorageManager.register(Y.StorageEngineHTML5);
- }());
- /*
- * Gears limitation:
- * - SQLite limitations - http://www.sqlite.org/limits.html
- * - DB Best Practices - http://code.google.com/apis/gears/gears_faq.html#bestPracticeDB
- * - the user must approve before gears can be used
- * - each SQL query has a limited number of characters (9948 bytes), data will need to be spread across rows
- * - no query should insert or update more than 9948 bytes of data in a single statement or GEARs will throw:
- * [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]
- *
- * Thoughts:
- * - we may want to implement additional functions for the gears only implementation
- * - how can we not use cookies to handle session location
- */
- (function() {
- // internal shorthand
- var Y = YAHOO.util,
- YL = YAHOO.lang,
- _SQL_STMT_LIMIT = 9948,
- _TABLE_NAME = 'YUIStorageEngine',
- // local variables
- _engine = null,
- eURI = encodeURIComponent,
- dURI = decodeURIComponent;
- /**
- * The StorageEngineGears class implements the Google Gears storage engine.
- * @namespace YAHOO.util
- * @class StorageEngineGears
- * @constructor
- * @extend YAHOO.util.Storage
- * @param location {String} Required. The storage location.
- * @param conf {Object} Required. A configuration object.
- */
- Y.StorageEngineGears = function(location, conf) {
- var _this = this;
- Y.StorageEngineGears.superclass.constructor.call(_this, location, Y.StorageEngineGears.ENGINE_NAME, conf);
- if (! _engine) {
- // create the database
- _engine = google.gears.factory.create(Y.StorageEngineGears.GEARS);
- _engine.open(window.location.host + '-' + Y.StorageEngineGears.DATABASE);
- _engine.execute('CREATE TABLE IF NOT EXISTS ' + _TABLE_NAME + ' (key TEXT, location TEXT, value TEXT)');
- }
- var isSessionStorage = Y.StorageManager.LOCATION_SESSION === _this._location,
- sessionKey = Y.Cookie.get('sessionKey' + Y.StorageEngineGears.ENGINE_NAME);
- if (! sessionKey) {
- _engine.execute('BEGIN');
- _engine.execute('DELETE FROM ' + _TABLE_NAME + ' WHERE location="' + eURI(Y.StorageManager.LOCATION_SESSION) + '"');
- _engine.execute('COMMIT');
- }
- var rs = _engine.execute('SELECT key FROM ' + _TABLE_NAME + ' WHERE location="' + eURI(_this._location) + '"'),
- keyMap = {};
-
- try {
- // iterate on the rows and map the keys
- while (rs.isValidRow()) {
- var fld = dURI(rs.field(0));
- if (! keyMap[fld]) {
- keyMap[fld] = true;
- _this._addKey(fld);
- }
- rs.next();
- }
- }
- finally {
- rs.close();
- }
- // this is session storage, ensure that the session key is set
- if (isSessionStorage) {
- Y.Cookie.set('sessionKey' + Y.StorageEngineGears.ENGINE_NAME, true);
- }
- _this.length = _this._keys.length;
- YL.later(250, _this, function() { // temporary solution so that CE_READY can be subscribed to after this object is created
- _this.fireEvent(_this.CE_READY);
- });
- };
- YL.extend(Y.StorageEngineGears, Y.StorageEngineKeyed, {
- /*
- * Implementation to clear the values from the storage engine.
- * @see YAHOO.util.Storage._clear
- */
- _clear: function() {
- _engine.execute('BEGIN');
- _engine.execute('DELETE FROM ' + _TABLE_NAME + ' WHERE location="' + eURI(this._location) + '"');
- _engine.execute('COMMIT');
- this._keys = [];
- this.length = 0;
- },
- /*
- * Implementation to fetch an item from the storage engine.
- * @see YAHOO.util.Storage._getItem
- */
- _getItem: function(key) {
- var rs = _engine.execute('SELECT value FROM ' + _TABLE_NAME + ' WHERE key="' + eURI(key) + '" AND location="' + eURI(this._location) + '"'),
- value = '';
- try {
- while (rs.isValidRow()) {
- var temp = rs.field(0);
- value += rs.field(0);
- rs.next();
- }
- }
- finally {
- rs.close();
- }
- return value ? dURI(value) : null;
- },
- /*
- * Implementation to fetch a key from the storage engine.
- * @see YAHOO.util.Storage.key
- */
- _key: function(index) {return this._keys[index];},
- /*
- * Implementation to remove an item from the storage engine.
- * @see YAHOO.util.Storage._removeItem
- */
- _removeItem: function(key) {
- YAHOO.log("removing " + key);
- _engine.execute('BEGIN');
- _engine.execute('DELETE FROM ' + _TABLE_NAME + ' WHERE key="' + eURI(key) + '" AND location="' + eURI(this._location) + '"');
- _engine.execute('COMMIT');
- this._removeKey(key);
- },
- /*
- * Implementation to remove an item from the storage engine.
- * @see YAHOO.util.Storage._setItem
- */
- _setItem: function(key, data) {
- YAHOO.log("SETTING " + data + " to " + key);
- if (! this.hasKey(key)) {
- this._addKey(key);
- }
- var _key = eURI(key),
- _location = eURI(this._location),
- _value = eURI(data),
- _values = [],
- _len = _SQL_STMT_LIMIT - (_key + _location).length;
- // the length of the value exceeds the available space
- if (_len < _value.length) {
- for (var i = 0, j = _value.length; i < j; i += _len) {
- _values.push(_value.substr(i, _len));
- }
- }
- else {
- _values.push(_value);
- }
- // Google recommends using INSERT instead of update, because it is faster
- _engine.execute('BEGIN');
- _engine.execute('DELETE FROM ' + _TABLE_NAME + ' WHERE key="' + eURI(key) + '" AND location="' + eURI(this._location) + '"');
- for (var m = 0, n = _values.length; m < n; m += 1) {
- _engine.execute('INSERT INTO ' + _TABLE_NAME + ' VALUES ("' + _key + '", "' + _location + '", "' + _values[m] + '")');
- }
- _engine.execute('COMMIT');
-
- return true;
- }
- });
- // releases the engine when the page unloads
- Y.Event.on('unload', function() {
- if (_engine) {_engine.close();}
- });
- Y.StorageEngineGears.ENGINE_NAME = 'gears';
- Y.StorageEngineGears.GEARS = 'beta.database';
- Y.StorageEngineGears.DATABASE = 'yui.database';
- Y.StorageEngineGears.isAvailable = function() {
- if (window.google && window.google.gears) {
- try {
- // this will throw an exception if the user denies gears
- google.gears.factory.create(Y.StorageEngineGears.GEARS);
- return true;
- }
- catch (e) {
- // no need to do anything
- }
- }
- return false;
- };
- Y.StorageManager.register(Y.StorageEngineGears);
- }());
- /*
- * SWF limitation:
- * - only 100,000 bytes of data may be stored this way
- * - data is publicly available on user machine
- *
- * Thoughts:
- * - data can be shared across browsers
- * - how can we not use cookies to handle session location
- */
- (function() {
- // internal shorthand
- var Y = YAHOO.util,
- YL = YAHOO.lang,
- YD = Y.Dom,
-
- /*
- * The minimum width required to be able to display the settings panel within the SWF.
- */
- MINIMUM_WIDTH = 215,
- /*
- * The minimum height required to be able to display the settings panel within the SWF.
- */
- MINIMUM_HEIGHT = 138,
- // local variables
- _engine = null,
- /*
- * Creates a location bound key.
- */
- _getKey = function(that, key) {
- return that._location + that.DELIMITER + key;
- },
- /*
- * Initializes the engine, if it isn't already initialized.
- */
- _initEngine = function(cfg) {
- if (! _engine) {
- if (! YL.isString(cfg.swfURL)) {cfg.swfURL = Y.StorageEngineSWF.SWFURL;}
- if (! cfg.containerID) {
- var bd = document.getElementsByTagName('body')[0],
- container = bd.appendChild(document.createElement('div'));
- cfg.containerID = YD.generateId(container);
- }
- if (! cfg.attributes) {cfg.attributes = {};}
- if (! cfg.attributes.flashVars) {cfg.attributes.flashVars = {};}
- cfg.attributes.flashVars.useCompression = 'true';
- cfg.attributes.version = 9.115;
- _engine = new YAHOO.widget.SWF(cfg.containerID, cfg.swfURL, cfg.attributes);
- }
- };
- /**
- * The StorageEngineSWF class implements the SWF storage engine.
- * @namespace YAHOO.util
- * @class StorageEngineSWF
- * @uses YAHOO.widget.SWF
- * @constructor
- * @extend YAHOO.util.Storage
- * @param location {String} Required. The storage location.
- * @param conf {Object} Required. A configuration object.
- */
- Y.StorageEngineSWF = function(location, conf) {
- var _this = this;
- Y.StorageEngineSWF.superclass.constructor.call(_this, location, Y.StorageEngineSWF.ENGINE_NAME, conf);
-
- _initEngine(_this._cfg);
- // evaluates when the SWF is loaded
- _engine.unsubscribe('contentReady'); // prevents local and session content ready callbacks from firing, when switching between context
- _engine.addListener("contentReady", function() {
- _this._swf = _engine._swf;
- _engine.initialized = true;
-
- var isSessionStorage = Y.StorageManager.LOCATION_SESSION === _this._location,
- sessionKey = Y.Cookie.get('sessionKey' + Y.StorageEngineSWF.ENGINE_NAME);
- for (var i = _engine.callSWF("getLength", []) - 1; 0 <= i; i -= 1) {
- var key = _engine.callSWF("getNameAt", [i]),
- isKeySessionStorage = -1 < key.indexOf(Y.StorageManager.LOCATION_SESSION + _this.DELIMITER);
- // this is session storage, but the session key is not set, so remove item
- if (isSessionStorage && ! sessionKey) {
- _engine.callSWF("removeItem", [key]);
- }
- // the key matches the storage type, add to key collection
- else if (isSessionStorage === isKeySessionStorage) {
- _this._addKey(key);
- }
- }
- // this is session storage, ensure that the session key is set
- if (isSessionStorage) {
- Y.Cookie.set('sessionKey' + Y.StorageEngineSWF.ENGINE_NAME, true);
- }
- _this.length = _this._keys.length;
- _this.fireEvent(_this.CE_READY);
- });
-
- // required for pages with both a session and local storage
- if (_engine.initialized) {_engine.fireEvent('contentReady');}
- };
- YL.extend(Y.StorageEngineSWF, Y.StorageEngineKeyed, {
- /**
- * The underlying SWF of the engine, exposed so developers can modify the adapter behavior.
- * @property _swf
- * @type {Object}
- * @protected
- */
- _swf: null,
- /*
- * Implementation to clear the values from the storage engine.
- * @see YAHOO.util.Storage._clear
- */
- _clear: function() {
- for (var i = this._keys.length - 1; 0 <= i; i -= 1) {
- var key = this._keys[i];
- _engine.callSWF("removeItem", [key]);
- }
- this._keys = [];
- this.length = 0;
- },
- /*
- * Implementation to fetch an item from the storage engine.
- * @see YAHOO.util.Storage._getItem
- */
- _getItem: function(key) {
- var _key = _getKey(this, key);
- return _engine.callSWF("getValueOf", [_key]);
- },
- /*
- * Implementation to fetch a key from the storage engine.
- * @see YAHOO.util.Storage.key
- */
- _key: function(index) {
- return (this._keys[index] || '').replace(/^.*?__/, '');
- },
- /*
- * Implementation to remove an item from the storage engine.
- * @see YAHOO.util.Storage._removeItem
- */
- _removeItem: function(key) {
- var _key = _getKey(this, key);
- _engine.callSWF("removeItem", [_key]);
- this._removeKey(_key);
- },
- /*
- * Implementation to remove an item from the storage engine.
- * @see YAHOO.util.Storage._setItem
- */
- _setItem: function(key, data) {
- var _key = _getKey(this, key), swfNode;
- // setting the value returns false if the value didn't change,
- // so I changed this to clear the key if it exists so that the
- // fork below works.
- if (_engine.callSWF("getValueOf", [_key])) {
- this._removeItem(key);
- }
- this._addKey(_key);
- if (_engine.callSWF("setItem", [_key, data])) {
- return true;
- } else {
- // @TODO we should not assume that a false return means that
- // the quota has been exceeded. this dialog should only be
- // displayed if the quotaExceededError event fired.
- swfNode = YD.get(_engine._id);
- if (MINIMUM_WIDTH > YD.getStyle(swfNode, 'width').replace(/\D+/g, '')) {
- YD.setStyle(swfNode, 'width', MINIMUM_WIDTH + 'px');
- }
- if (MINIMUM_HEIGHT > YD.getStyle(swfNode, 'height').replace(/\D+/g, '')) {
- YD.setStyle(swfNode, 'height', MINIMUM_HEIGHT + 'px');
- }
- return _engine.callSWF("displaySettings", []);
- }
- }
- });
- Y.StorageEngineSWF.SWFURL = "swfstore.swf";
- Y.StorageEngineSWF.ENGINE_NAME = 'swf';
- Y.StorageEngineSWF.isAvailable = function() {
- return (6 <= YAHOO.env.ua.flash && YAHOO.widget.SWF);
- };
- Y.StorageManager.register(Y.StorageEngineSWF);
- }());
- YAHOO.register("storage", YAHOO.util.Storage, {version: "2.8.0r4", build: "2449"});
|