Yahoo! UI Library

Storage  2.8.0r4

Yahoo! UI Library > Storage > Storage.js (source view)
Search:
 
Filters
/**
 * 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);
}

}());

Copyright © 2009 Yahoo! Inc. All rights reserved.