[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/2in3/2.9.0/build/yui2-storage/ -> yui2-storage-debug.js (source)

   1  YUI.add('yui2-storage', function(Y) {
   2      var YAHOO    = Y.YUI2;
   3      /*
   4  Copyright (c) 2011, Yahoo! Inc. All rights reserved.
   5  Code licensed under the BSD License:
   6  http://developer.yahoo.com/yui/license.html
   7  version: 2.9.0
   8  */
   9  /**
  10   * The Storage module manages client-side data storage.
  11   * @module Storage
  12   */
  13  
  14  (function() {
  15  
  16      // internal shorthand
  17  var Y = YAHOO,
  18      Util = Y.util,
  19      Lang = Y.lang,
  20      _logOverwriteError,
  21      Storage,
  22  
  23      RX_TYPE = /^type=(\w+)/i,
  24      RX_VALUE = /&value=(.*)/i;
  25  
  26  if (! Util.Storage) {
  27      _logOverwriteError = function(fxName) {
  28          Y.log('Exception in YAHOO.util.Storage.?? - must be extended by a storage engine'.replace('??', fxName).replace('??', this.getName ? this.getName() : 'Unknown'), 'error');
  29      };
  30  
  31      /**
  32       * The Storage class is an HTML 5 storage API clone, used to wrap individual storage implementations with a common API.
  33       * @class Storage
  34       * @namespace YAHOO.util
  35       * @constructor
  36       * @param sLocation {String} Required. The storage location.
  37       * @parm sName {String} Required. The engine name.
  38       * @param oConf {Object} Required. A configuration object.
  39       */
  40      Storage = function(sLocation, sName, oConf) {
  41          var that = this;
  42          Y.env._id_counter += 1;
  43  
  44          // protected variables
  45          that._cfg = Lang.isObject(oConf) ? oConf : {};
  46          that._location = sLocation;
  47          that._name = sName;
  48          that.isReady = false;
  49  
  50          // public variables
  51          that.createEvent(Storage.CE_READY, {scope: that, fireOnce: true});
  52          that.createEvent(Storage.CE_CHANGE, {scope: that});
  53          
  54          that.subscribe(Storage.CE_READY, function() {
  55              that.isReady = true;
  56          });
  57      };
  58  
  59      Storage.CE_READY = 'YUIStorageReady';
  60      Storage.CE_CHANGE = 'YUIStorageChange';
  61  
  62      Storage.prototype = {
  63  
  64          /**
  65           * The event name for when the storage item is ready.
  66           * @property CE_READY
  67           * @type {String}
  68           * @public
  69           */
  70          CE_READY: Storage.CE_READY,
  71  
  72          /**
  73           * The event name for when the storage item has changed.
  74           * @property CE_CHANGE
  75           * @type {String}
  76           * @public
  77           */
  78          CE_CHANGE: Storage.CE_CHANGE,
  79  
  80          /**
  81           * The configuration of the engine.
  82           * @property _cfg
  83           * @type {Object}
  84           * @protected
  85           */
  86          _cfg: '',
  87  
  88          /**
  89           * The name of this engine.
  90           * @property _name
  91           * @type {String}
  92           * @protected
  93           */
  94          _name: '',
  95  
  96          /**
  97           * The location for this instance.
  98           * @property _location
  99           * @type {String}
 100           * @protected
 101           */
 102          _location: '',
 103  
 104          /**
 105           * The current length of the keys.
 106           * @property length
 107           * @type {Number}
 108           * @public
 109           */
 110          length: 0,
 111  
 112          /**
 113           * This engine singleton has been initialized already.
 114           * @property isReady
 115           * @type {String}
 116           * @protected
 117           */
 118          isReady: false,
 119  
 120          /**
 121           * Clears any existing key/value pairs.
 122           * @method clear
 123           * @public
 124           */
 125          clear: function() {
 126              this._clear();
 127              this.length = 0;
 128          },
 129  
 130          /**
 131           * Fetches the data stored and the provided key.
 132           * @method getItem
 133           * @param sKey {String} Required. The key used to reference this value (DOMString in HTML 5 spec).
 134           * @return {String|NULL} The value stored at the provided key (DOMString in HTML 5 spec).
 135           * @public
 136           */
 137          getItem: function(sKey) {
 138              Y.log("Fetching item at  " + sKey);
 139              var oItem = this._getItem(sKey);
 140              return Lang.isValue(oItem) ? this._getValue(oItem) : null; // required by HTML 5 spec
 141          },
 142  
 143          /**
 144           * Fetches the storage object's name; should be overwritten by storage engine.
 145           * @method getName
 146           * @return {String} The name of the data storage object.
 147           * @public
 148           */
 149          getName: function() {return this._name;},
 150  
 151          /**
 152           * Tests if the key has been set (not in HTML 5 spec); should be overwritten by storage engine.
 153           * @method hasKey
 154           * @param sKey {String} Required. The key to search for.
 155           * @return {Boolean} True when key has been set.
 156           * @public
 157           */
 158          hasKey: function(sKey) {
 159              return Lang.isString(sKey) && this._hasKey(sKey);
 160          },
 161  
 162          /**
 163           * Retrieve the key stored at the provided index; should be overwritten by storage engine.
 164           * @method key
 165           * @param nIndex {Number} Required. The index to retrieve (unsigned long in HTML 5 spec).
 166           * @return {String} Required. The key at the provided index (DOMString in HTML 5 spec).
 167           * @public
 168           */
 169          key: function(nIndex) {
 170              Y.log("Fetching key at " + nIndex);
 171  
 172              if (Lang.isNumber(nIndex) && -1 < nIndex && this.length > nIndex) {
 173                  var value = this._key(nIndex);
 174                  if (value) {return value;}
 175              }
 176  
 177              // this is thrown according to the HTML5 spec
 178              throw('INDEX_SIZE_ERR - Storage.setItem - The provided index (' + nIndex + ') is not available');
 179          },
 180  
 181          /**
 182           * Remove an item from the data storage.
 183           * @method removeItem
 184           * @param sKey {String} Required. The key to remove (DOMString in HTML 5 spec).
 185           * @public
 186           */
 187          removeItem: function(sKey) {
 188              Y.log("removing " + sKey);
 189              var that = this,
 190                  oOldValue;
 191              
 192              if (that.hasKey(sKey)) {
 193                  oOldValue = that._getItem(sKey);
 194                  if (! oOldValue) {oOldValue = null;}
 195                  that._removeItem(sKey);
 196                  that.fireEvent(Storage.CE_CHANGE, new Util.StorageEvent(that, sKey, oOldValue, null, Util.StorageEvent.TYPE_REMOVE_ITEM));
 197              }
 198              else {
 199                  // HTML 5 spec says to do nothing
 200              }
 201          },
 202  
 203          /**
 204           * Adds an item to the data storage.
 205           * @method setItem
 206           * @param sKey {String} Required. The key used to reference this value (DOMString in HTML 5 spec).
 207           * @param oData {Object} Required. The data to store at key (DOMString in HTML 5 spec).
 208           * @public
 209           * @throws QUOTA_EXCEEDED_ERROR
 210           */
 211          setItem: function(sKey, oData) {
 212              Y.log("SETTING " + oData + " to " + sKey);
 213              
 214              if (Lang.isString(sKey)) {
 215                  var that = this,
 216                      oOldValue = that._getItem(sKey);
 217  
 218                  if (! oOldValue) {oOldValue = null;}
 219  
 220                  if (that._setItem(sKey, that._createValue(oData))) {
 221                      that.fireEvent(Storage.CE_CHANGE, new Util.StorageEvent(that, sKey, oOldValue, oData,
 222                              that.hasKey(sKey) ? Util.StorageEvent.TYPE_UPDATE_ITEM : Util.StorageEvent.TYPE_ADD_ITEM));
 223                  }
 224                  else {
 225                      // that is thrown according to the HTML5 spec
 226                      throw('QUOTA_EXCEEDED_ERROR - Storage.setItem - The choosen storage method (' +
 227                            that.getName() + ') has exceeded capacity');
 228                  }
 229              }
 230              else {
 231                  // HTML 5 spec says to do nothing
 232              }
 233          },
 234  
 235          /**
 236           * Implementation of the clear login; should be overwritten by storage engine.
 237           * @method _clear
 238           * @protected
 239           */
 240          _clear: function() {
 241              _logOverwriteError('_clear');
 242              return '';
 243          },
 244  
 245          /**
 246           * Converts the object into a string, with meta data (type), so it can be restored later.
 247           * @method _createValue
 248           * @param o {Object} Required. An object to store.
 249           * @protected
 250           */
 251          _createValue: function(o) {
 252              var sType = (Lang.isNull(o) || Lang.isUndefined(o)) ? ('' + o) : typeof o;
 253              return 'type=' + sType + '&value=' + encodeURIComponent('' + o);
 254          },
 255  
 256          /**
 257           * Implementation of the getItem login; should be overwritten by storage engine.
 258           * @method _getItem
 259           * @param sKey {String} Required. The key used to reference this value.
 260           * @return {String|NULL} The value stored at the provided key.
 261           * @protected
 262           */
 263          _getItem: function(sKey) {
 264              _logOverwriteError('_getItem');
 265              return '';
 266          },
 267  
 268          /**
 269           * Converts the stored value into its appropriate type.
 270           * @method _getValue
 271           * @param s {String} Required. The stored value.
 272           * @protected
 273           */
 274          _getValue: function(s) {
 275              var sType = s.match(RX_TYPE)[1],
 276                  sValue = s.match(RX_VALUE)[1];
 277  
 278              switch (sType) {
 279                  case 'boolean': return 'true' == sValue;
 280                  case 'number': return parseFloat(sValue);
 281                  case 'null': return null;
 282                  default: return decodeURIComponent(sValue);
 283              }
 284          },
 285  
 286          /**
 287           * Implementation of the key logic; should be overwritten by storage engine.
 288           * @method _key
 289           * @param nIndex {Number} Required. The index to retrieve (unsigned long in HTML 5 spec).
 290           * @return {String|NULL} Required. The key at the provided index (DOMString in HTML 5 spec).
 291           * @protected
 292           */
 293          _key: function(nIndex) {
 294              _logOverwriteError('_key');
 295              return '';
 296          },
 297  
 298          /*
 299           * Implementation to fetch evaluate the existence of a key.
 300           */
 301          _hasKey: function(sKey) {
 302              return null !== this._getItem(sKey);
 303          },
 304  
 305          /**
 306           * Implementation of the removeItem login; should be overwritten by storage engine.
 307           * @method _removeItem
 308           * @param sKey {String} Required. The key to remove.
 309           * @protected
 310           */
 311          _removeItem: function(sKey) {
 312              _logOverwriteError('_removeItem');
 313              return '';
 314          },
 315  
 316          /**
 317           * Implementation of the setItem login; should be overwritten by storage engine.
 318           * @method _setItem
 319           * @param sKey {String} Required. The key used to reference this value.
 320           * @param oData {Object} Required. The data to storage at key.
 321           * @return {Boolean} True when successful, false when size QUOTA exceeded.
 322           * @protected
 323           */
 324          _setItem: function(sKey, oData) {
 325              _logOverwriteError('_setItem');
 326              return '';
 327          }
 328      };
 329  
 330      Lang.augmentProto(Storage, Util.EventProvider);
 331  
 332      Util.Storage = Storage;
 333  }
 334  
 335  }());
 336  /**
 337   * The StorageManager class is a singleton that registers DataStorage objects and returns instances of those objects.
 338   * @class StorageManager
 339   * @namespace YAHOO.util
 340   * @static
 341   */
 342  (function() {
 343      // internal shorthand
 344  var Util = YAHOO.util,
 345      Lang = YAHOO.lang,
 346  
 347      // private variables
 348      _locationEngineMap = {}, // cached engines
 349      _registeredEngineSet = [], // set of available engines
 350      _registeredEngineMap = {}, // map of available engines
 351      
 352      /**
 353       * Fetches a storage constructor if it is available, otherwise returns NULL.
 354       * @method _getClass
 355       * @param fnClass {Function} Required. The storage constructor to test.
 356       * @return {Function} An available storage constructor or NULL.
 357       * @private
 358       */
 359      _getClass = function(fnClass) {
 360          return (fnClass && fnClass.isAvailable()) ? fnClass : null;
 361      },
 362  
 363      /**
 364       * Fetches the storage engine from the cache, or creates and caches it.
 365       * @method _getStorageEngine
 366       * @param sLocation {String} Required. The location to store.
 367       * @param fnClass {Function} Required. A pointer to the engineType Class.
 368       * @param oConf {Object} Optional. Additional configuration for the data source engine.
 369       * @private
 370       */
 371      _getStorageEngine = function(sLocation, fnClass, oConf) {
 372          var engine = _locationEngineMap[sLocation + fnClass.ENGINE_NAME];
 373  
 374          if (! engine) {
 375              engine = new fnClass(sLocation, oConf);
 376              _locationEngineMap[sLocation + fnClass.ENGINE_NAME] = engine;
 377          }
 378  
 379          return engine;
 380      },
 381  
 382      /**
 383       * Ensures that the location is valid before returning it or a default value.
 384       * @method _getValidLocation
 385       * @param sLocation {String} Required. The location to evaluate.
 386       * @private
 387       */
 388      _getValidLocation = function(sLocation) {
 389          switch (sLocation) {
 390              case Util.StorageManager.LOCATION_LOCAL:
 391              case Util.StorageManager.LOCATION_SESSION:
 392                  return sLocation;
 393  
 394              default: return Util.StorageManager.LOCATION_SESSION;
 395          }
 396      };
 397  
 398      // public namespace
 399      Util.StorageManager = {
 400  
 401          /**
 402           * The storage location - session; data cleared at the end of a user's session.
 403           * @property LOCATION_SESSION
 404           * @type {String}
 405           * @static
 406           */
 407          LOCATION_SESSION: 'sessionStorage',
 408  
 409          /**
 410           * The storage location - local; data cleared on demand.
 411           * @property LOCATION_LOCAL
 412           * @type {String}
 413           * @static
 414           */
 415          LOCATION_LOCAL: 'localStorage',
 416  
 417          /**
 418           * Fetches the desired engine type or first available engine type.
 419           * @method get
 420           * @param engineType {String} Optional. The engine type, see engines.
 421           * @param sLocation {String} Optional. The storage location - LOCATION_SESSION & LOCATION_LOCAL; default is LOCAL.
 422           * @param oConf {Object} Optional. Additional configuration for the getting the storage engine.
 423           * {
 424           *     engine: {Object} configuration parameters for the desired engine
 425           *     force: {Boolean} force the <code>engineType</code> or fail
 426           *     order: {Array} an array of storage engine names; the desired order to try engines}
 427           * }
 428           * @static
 429           */
 430          get: function(engineType, sLocation, oConf) {
 431              var oCfg = Lang.isObject(oConf) ? oConf : {},
 432                  fnClass = _getClass(_registeredEngineMap[engineType]),
 433                  i , j;
 434  
 435              if (! fnClass && ! oCfg.force) {
 436                  if (oCfg.order) {
 437                      j = oCfg.order.length;
 438  
 439                      for (i = 0; i < j && ! fnClass; i += 1) {
 440                          fnClass = _getClass(oCfg.order[i]);
 441                      }
 442                  }
 443  
 444                  if (! fnClass) {
 445                      j = _registeredEngineSet.length;
 446  
 447                      for (i = 0; i < j && ! fnClass; i += 1) {
 448                          fnClass = _getClass(_registeredEngineSet[i]);
 449                      }
 450                  }
 451              }
 452  
 453              if (fnClass) {
 454                  return _getStorageEngine(_getValidLocation(sLocation), fnClass, oCfg.engine);
 455              }
 456  
 457              throw('YAHOO.util.StorageManager.get - No engine available, please include an engine before calling this function.');
 458          },
 459  
 460          /*
 461           * Estimates the size of the string using 1 byte for each alpha-numeric character and 3 for each non-alpha-numeric character.
 462           * @method getByteSize
 463           * @param s {String} Required. The string to evaulate.
 464           * @return {Number} The estimated string size.
 465           * @private
 466           */
 467          getByteSize: function(s) {
 468              return encodeURIComponent('' + s).length;
 469          },
 470  
 471          /**
 472           * Registers a engineType Class with the StorageManager singleton; first in is the first out.
 473           * @method register
 474           * @param engineConstructor {Function} Required. The engine constructor function, see engines.
 475           * @return {Boolean} When successfully registered.
 476           * @static
 477           */
 478          register: function(engineConstructor) {
 479              if (Lang.isFunction(engineConstructor) && Lang.isFunction(engineConstructor.isAvailable) &&
 480                      Lang.isString(engineConstructor.ENGINE_NAME)) {
 481                  _registeredEngineMap[engineConstructor.ENGINE_NAME] = engineConstructor;
 482                  _registeredEngineSet.push(engineConstructor);
 483                  return true;
 484              }
 485  
 486              return false;
 487          }
 488      };
 489  
 490      YAHOO.register("StorageManager", Util.SWFStore, {version: "2.9.0", build: "2800"});
 491  }());
 492  (function() {
 493  
 494  /**
 495   * The StorageEvent class manages the storage events by emulating the HTML 5 implementation.
 496   * @namespace YAHOO.util
 497   * @class StorageEvent
 498   * @constructor
 499   * @param oStorageArea {Object} Required. The Storage object that was affected.
 500   * @param sKey {String} Required. The key being changed; DOMString in HTML 5 spec.
 501   * @param oOldValue {Mixed} Required. The old value of the key being changed; DOMString in HTML 5 spec.
 502   * @param oNewValue {Mixed} Required. The new value of the key being changed; DOMString in HTML 5 spec.
 503   * @param sType {String} Required. The storage event type.
 504   */
 505  function StorageEvent(oStorageArea, sKey, oOldValue, oNewValue, sType) {
 506      this.key = sKey;
 507      this.oldValue = oOldValue;
 508      this.newValue = oNewValue;
 509      this.url = window.location.href;
 510      this.window = window; // todo: think about the CAJA and innocent code
 511      this.storageArea = oStorageArea;
 512      this.type = sType;
 513  }
 514  
 515  YAHOO.lang.augmentObject(StorageEvent, {
 516      TYPE_ADD_ITEM: 'addItem',
 517      TYPE_REMOVE_ITEM: 'removeItem',
 518      TYPE_UPDATE_ITEM: 'updateItem'
 519  });
 520  
 521  StorageEvent.prototype = {
 522  
 523      /**
 524       * The 'key' attribute represents the key being changed.
 525       * @property key
 526       * @type {String}
 527       * @static
 528       * @readonly
 529       */
 530      key: null,
 531  
 532      /**
 533       * The 'newValue' attribute represents the new value of the key being changed.
 534       * @property newValue
 535       * @type {Mixed}
 536       * @static
 537       * @readonly
 538       */
 539      newValue: null,
 540  
 541      /**
 542       * The 'oldValue' attribute represents the old value of the key being changed.
 543       * @property oldValue
 544       * @type {Mixed}
 545       * @static
 546       * @readonly
 547       */
 548      oldValue: null,
 549  
 550      /**
 551       * The 'source' attribute represents the WindowProxy object of the browsing context of the document whose key changed.
 552       * @property source
 553       * @type {Object}
 554       * @static
 555       * @readonly
 556       */
 557      source: null,
 558  
 559      /**
 560       * The 'storageArea' attribute represents the Storage object that was affected.
 561       * @property storageArea
 562       * @type {Object}
 563       * @static
 564       * @readonly
 565       */
 566      storageArea: null,
 567  
 568      /**
 569       * The 'type' attribute represents the Storage event type.
 570       * @property type
 571       * @type {Object}
 572       * @static
 573       * @readonly
 574       */
 575      type: null,
 576  
 577      /**
 578       * The 'url' attribute represents the address of the document whose key changed.
 579       * @property url
 580       * @type {String}
 581       * @static
 582       * @readonly
 583       */
 584      url: null
 585  };
 586  
 587  YAHOO.util.StorageEvent = StorageEvent;
 588      
 589  }());
 590  (function() {
 591  var Util = YAHOO.util;
 592  
 593      /**
 594       * The StorageEngineKeyed class implements the interface necessary for managing keys.
 595       * @namespace YAHOO.util
 596       * @class StorageEngineKeyed
 597       * @constructor
 598       * @extend YAHOO.util.Storage
 599       */
 600      Util.StorageEngineKeyed = function() {
 601          Util.StorageEngineKeyed.superclass.constructor.apply(this, arguments);
 602          this._keys = [];
 603          this._keyMap = {};
 604      };
 605  
 606      YAHOO.lang.extend(Util.StorageEngineKeyed, Util.Storage, {
 607  
 608          /**
 609           * A collection of keys applicable to the current location. This should never be edited by the developer.
 610           * @property _keys
 611           * @type {Array}
 612           * @protected
 613           */
 614          _keys: null,
 615  
 616          /**
 617           * A map of keys to their applicable position in keys array. This should never be edited by the developer.
 618           * @property _keyMap
 619           * @type {Object}
 620           * @protected
 621           */
 622          _keyMap: null,
 623  
 624          /**
 625           * Adds the key to the set.
 626           * @method _addKey
 627           * @param sKey {String} Required. The key to evaluate.
 628           * @protected
 629           */
 630          _addKey: function(sKey) {
 631              if (!this._keyMap.hasOwnProperty(sKey)) {
 632                  this._keys.push(sKey);
 633                  this._keyMap[sKey] = this.length;
 634                  this.length = this._keys.length;
 635              }
 636          },
 637  
 638          /*
 639           * Implementation to clear the values from the storage engine.
 640           * @see YAHOO.util.Storage._clear
 641           */
 642          _clear: function() {
 643              this._keys = [];
 644              this.length = 0;
 645          },
 646  
 647          /**
 648           * Evaluates if a key exists in the keys array; indexOf does not work in all flavors of IE.
 649           * @method _indexOfKey
 650           * @param sKey {String} Required. The key to evaluate.
 651           * @protected
 652           */
 653          _indexOfKey: function(sKey) {
 654              var i = this._keyMap[sKey];
 655              return undefined === i ? -1 : i;
 656          },
 657  
 658          /*
 659           * Implementation to fetch a key from the storage engine.
 660           * @see YAHOO.util.Storage.key
 661           */
 662          _key: function(nIndex) {return this._keys[nIndex];},
 663  
 664          /**
 665           * Removes a key from the keys array.
 666           * @method _removeItem
 667           * @param sKey {String} Required. The key to remove.
 668           * @protected
 669           */
 670          _removeItem: function(sKey) {
 671              var that = this,
 672                  j = that._indexOfKey(sKey),
 673                  rest = that._keys.slice(j + 1),
 674                  k;
 675  
 676              delete that._keyMap[sKey];
 677  
 678              // update values in keymap that are greater than current position
 679              for (k in that._keyMap) {
 680                  if (j < that._keyMap[k]) {
 681                      that._keyMap[k] -= 1;
 682                  }
 683              }
 684              
 685              that._keys.length = j;
 686              that._keys = that._keys.concat(rest);
 687              that.length = that._keys.length;
 688          }
 689      });
 690  }());
 691  /*
 692   * HTML limitations:
 693   *  - 5MB in FF and Safari, 10MB in IE 8
 694   *  - only FF 3.5 recovers session storage after a browser crash
 695   *
 696   * Thoughts:
 697   *  - how can we not use cookies to handle session
 698   */
 699  (function() {
 700      // internal shorthand
 701  var Util = YAHOO.util,
 702      Lang = YAHOO.lang,
 703  
 704      /*
 705       * Required for IE 8 to make synchronous.
 706       */
 707      _beginTransaction = function(driver) {
 708          driver.begin();
 709      },
 710  
 711      /*
 712       * Required for IE 8 to make synchronous.
 713       */
 714      _commitTransaction = function(driver) {
 715          driver.commit();
 716      },
 717  
 718      /**
 719       * The StorageEngineHTML5 class implements the HTML5 storage engine.
 720       * @namespace YAHOO.util
 721       * @class StorageEngineHTML5
 722       * @constructor
 723       * @extend YAHOO.util.Storage
 724       * @param sLocation {String} Required. The storage location.
 725       * @param oConf {Object} Required. A configuration object.
 726       */
 727      StorageEngineHTML5 = function(sLocation, oConf) {
 728          var that = this,
 729              oDriver = window[sLocation];
 730          
 731          StorageEngineHTML5.superclass.constructor.call(that, sLocation, StorageEngineHTML5.ENGINE_NAME, oConf);// not set, are cookies available
 732  
 733          // simplifieds the begin/commit functions, if not using IE; this provides a massive performance boost
 734          if (! oDriver.begin) {_beginTransaction = function() {}; }
 735          if (! oDriver.commit) {_commitTransaction = function() {}; }
 736  
 737          that.length = oDriver.length;
 738          that._driver = oDriver;
 739          that.fireEvent(Util.Storage.CE_READY);
 740      };
 741  
 742      Lang.extend(StorageEngineHTML5, Util.Storage, {
 743  
 744          _driver: null,
 745  
 746          /*
 747           * Implementation to clear the values from the storage engine.
 748           * @see YAHOO.util.Storage._clear
 749           */
 750          _clear: function() {
 751              var that = this, i, sKey;
 752  
 753              if (that._driver.clear) {
 754                  that._driver.clear();
 755              }
 756              // for FF 3, fixed in FF 3.5
 757              else {
 758                  for (i = that.length; 0 <= i; i -= 1) {
 759                      sKey = that._key(i);
 760                      that._removeItem(sKey);
 761                  }
 762              }
 763          },
 764  
 765          /*
 766           * Implementation to fetch an item from the storage engine.
 767           * @see YAHOO.util.Storage._getItem
 768           */
 769          _getItem: function(sKey) {
 770              var o = this._driver.getItem(sKey);
 771              return Lang.isObject(o) ? o.value : o; // for FF 3, fixed in FF 3.5
 772          },
 773  
 774          /*
 775           * Implementation to fetch a key from the storage engine.
 776           * @see YAHOO.util.Storage._key
 777           */
 778          _key: function(nIndex) {return this._driver.key(nIndex);},
 779  
 780          /*
 781           * Implementation to remove an item from the storage engine.
 782           * @see YAHOO.util.Storage._removeItem
 783           */
 784          _removeItem: function(sKey) {
 785              var oDriver = this._driver;
 786              _beginTransaction(oDriver);
 787              oDriver.removeItem(sKey);
 788              _commitTransaction(oDriver);
 789              this.length = oDriver.length;
 790          },
 791  
 792          /*
 793           * Implementation to remove an item from the storage engine.
 794           * @see YAHOO.util.Storage._setItem
 795           */
 796          _setItem: function(sKey, oValue) {
 797              var oDriver = this._driver;
 798  
 799              try {
 800                  _beginTransaction(oDriver);
 801                  oDriver.setItem(sKey, oValue);
 802                  _commitTransaction(oDriver);
 803                  this.length = oDriver.length;
 804                  return true;
 805              }
 806              catch (e) {
 807                  return false;
 808              }
 809          }
 810      }, true);
 811  
 812      StorageEngineHTML5.ENGINE_NAME = 'html5';
 813      
 814      StorageEngineHTML5.isAvailable = function() {
 815          try {
 816              return ('localStorage' in window) && window['localStorage'] !== null &&
 817                      ('sessionStorage' in window) && window['sessionStorage'] !== null;
 818          }
 819          catch (e) {
 820              /*
 821                  In FireFox and maybe other browsers, you can disable storage in the configuration settings, which
 822                  will cause an error to be thrown instead of evaluating the simple if/else statement.
 823               */
 824              return false;
 825          }
 826      };
 827  
 828      Util.StorageManager.register(StorageEngineHTML5);
 829      Util.StorageEngineHTML5 = StorageEngineHTML5;
 830  }());
 831  /*
 832   * Gears limitation:
 833   *  - SQLite limitations - http://www.sqlite.org/limits.html
 834   *  - DB Best Practices - http://code.google.com/apis/gears/gears_faq.html#bestPracticeDB
 835   *     - the user must approve before gears can be used
 836   *  - each SQL query has a limited number of characters (9948 bytes), data will need to be spread across rows
 837   *  - no query should insert or update more than 9948 bytes of data in a single statement or GEARs will throw:
 838   *      [Exception... "'Error: SQL statement is too long.' when calling method: [nsIDOMEventListener::handleEvent]" nsresult: "0x8057001c (NS_ERROR_XPC_JS_THREW_JS_OBJECT)" location: "<unknown>" data: no]
 839   *
 840   * Thoughts:
 841   *  - we may want to implement additional functions for the gears only implementation
 842   *  - how can we not use cookies to handle session location
 843   */
 844  (function() {
 845      // internal shorthand
 846  var Util = YAHOO.util,
 847      Lang = YAHOO.lang,
 848      SQL_STMT_LIMIT = 9948,
 849      TABLE_NAME = 'YUIStorageEngine',
 850  
 851      // local variables
 852      _driver = null,
 853  
 854      eURI = encodeURIComponent,
 855      dURI = decodeURIComponent,
 856  
 857      /**
 858       * The StorageEngineGears class implements the Google Gears storage engine.
 859       * @namespace YAHOO.util
 860       * @class StorageEngineGears
 861       * @constructor
 862       * @extend YAHOO.util.Storage
 863       * @param sLocation {String} Required. The storage location.
 864       * @param oConf {Object} Required. A configuration object.
 865       */
 866      StorageEngineGears = function(sLocation, oConf) {
 867          var that = this,
 868              keyMap = {},
 869              isSessionStorage, sessionKey, rs;
 870          
 871          StorageEngineGears.superclass.constructor.call(that, sLocation, StorageEngineGears.ENGINE_NAME, oConf);
 872  
 873          if (! _driver) {
 874              // create the database
 875              _driver = google.gears.factory.create(StorageEngineGears.GEARS);
 876        // the replace regex fixes http://yuilibrary.com/projects/yui2/ticket/2529411, all ascii characters are allowede except / : * ? " < > | ; ,
 877              _driver.open(window.location.host.replace(/[\/\:\*\?"\<\>\|;,]/g, '') + '-' + StorageEngineGears.DATABASE);
 878              _driver.execute('CREATE TABLE IF NOT EXISTS ' + TABLE_NAME + ' (key TEXT, location TEXT, value TEXT)');
 879          }
 880  
 881          isSessionStorage = Util.StorageManager.LOCATION_SESSION === that._location;
 882          sessionKey = Util.Cookie.get('sessionKey' + StorageEngineGears.ENGINE_NAME);
 883  
 884          if (! sessionKey) {
 885              _driver.execute('BEGIN');
 886              _driver.execute('DELETE FROM ' + TABLE_NAME + ' WHERE location="' + eURI(Util.StorageManager.LOCATION_SESSION) + '"');
 887              _driver.execute('COMMIT');
 888          }
 889  
 890          rs = _driver.execute('SELECT key FROM ' + TABLE_NAME + ' WHERE location="' + eURI(that._location) + '"');
 891          keyMap = {};
 892      
 893          try {
 894              // iterate on the rows and map the keys
 895              while (rs.isValidRow()) {
 896                  var fld = dURI(rs.field(0));
 897  
 898                  if (! keyMap[fld]) {
 899                      keyMap[fld] = true;
 900                      that._addKey(fld);
 901                  }
 902  
 903                  rs.next();
 904              }
 905          } finally {
 906              rs.close();
 907          }
 908  
 909          // this is session storage, ensure that the session key is set
 910          if (isSessionStorage) {
 911              Util.Cookie.set('sessionKey' + StorageEngineGears.ENGINE_NAME, true);
 912          }
 913  
 914          that.fireEvent(Util.Storage.CE_READY);
 915      };
 916  
 917      Lang.extend(StorageEngineGears, Util.StorageEngineKeyed, {
 918  
 919          /*
 920           * Implementation to clear the values from the storage engine.
 921           * @see YAHOO.util.Storage._clear
 922           */
 923          _clear: function() {
 924              StorageEngineGears.superclass._clear.call(this);
 925              _driver.execute('BEGIN');
 926              _driver.execute('DELETE FROM ' + TABLE_NAME + ' WHERE location="' + eURI(this._location) + '"');
 927              _driver.execute('COMMIT');
 928          },
 929  
 930          /*
 931           * Implementation to fetch an item from the storage engine.
 932           * @see YAHOO.util.Storage._getItem
 933           */
 934          _getItem: function(sKey) {
 935              var rs = _driver.execute('SELECT value FROM ' + TABLE_NAME + ' WHERE key="' + eURI(sKey) + '" AND location="' + eURI(this._location) + '"'),
 936                  value = '';
 937  
 938              try {
 939                  while (rs.isValidRow()) {
 940                      value += rs.field(0);
 941                      rs.next();
 942                  }
 943              } finally {
 944                  rs.close();
 945              }
 946  
 947              return value ? dURI(value) : null;
 948          },
 949  
 950          /*
 951           * Implementation to remove an item from the storage engine.
 952           * @see YAHOO.util.Storage._removeItem
 953           */
 954          _removeItem: function(sKey) {
 955              YAHOO.log("removing gears key: " + sKey);
 956              StorageEngineGears.superclass._removeItem.call(this, sKey);
 957              _driver.execute('BEGIN');
 958              _driver.execute('DELETE FROM ' + TABLE_NAME + ' WHERE key="' + eURI(sKey) + '" AND location="' + eURI(this._location) + '"');
 959              _driver.execute('COMMIT');
 960          },
 961  
 962          /*
 963           * Implementation to remove an item from the storage engine.
 964           * @see YAHOO.util.Storage._setItem
 965           */
 966          _setItem: function(sKey, oData) {
 967              YAHOO.log("SETTING " + oData + " to " + sKey);
 968  
 969              this._addKey(sKey);
 970  
 971              var sEscapedKey = eURI(sKey),
 972                  sEscapedLocation = eURI(this._location),
 973                  sEscapedValue = eURI(oData), // escaped twice, maybe not necessary
 974                  aValues = [],
 975                  nLen = SQL_STMT_LIMIT - (sEscapedKey + sEscapedLocation).length,
 976                  i=0, j;
 977  
 978              // the length of the value exceeds the available space
 979              if (nLen < sEscapedValue.length) {
 980                  for (j = sEscapedValue.length; i < j; i += nLen) {
 981                      aValues.push(sEscapedValue.substr(i, nLen));
 982                  }
 983              } else {
 984                  aValues.push(sEscapedValue);
 985              }
 986  
 987              // Google recommends using INSERT instead of update, because it is faster
 988              _driver.execute('BEGIN');
 989              _driver.execute('DELETE FROM ' + TABLE_NAME + ' WHERE key="' + sEscapedKey + '" AND location="' + sEscapedLocation + '"');
 990              for (i = 0, j = aValues.length; i < j; i += 1) {
 991                  _driver.execute('INSERT INTO ' + TABLE_NAME + ' VALUES ("' + sEscapedKey + '", "' + sEscapedLocation + '", "' + aValues[i] + '")');
 992              }
 993              _driver.execute('COMMIT');
 994              
 995              return true;
 996          }
 997      });
 998  
 999      // releases the engine when the page unloads
1000      Util.Event.on('unload', function() {
1001          if (_driver) {_driver.close();}
1002      });
1003  
1004      StorageEngineGears.ENGINE_NAME = 'gears';
1005      StorageEngineGears.GEARS = 'beta.database';
1006      StorageEngineGears.DATABASE = 'yui.database';
1007  
1008      StorageEngineGears.isAvailable = function() {
1009          if (('google' in window) && ('gears' in window.google)) {
1010              try {
1011                  // this will throw an exception if the user denies gears
1012                  google.gears.factory.create(StorageEngineGears.GEARS);
1013                  return true;
1014              }
1015              catch (e) {
1016                  // no need to do anything
1017              }
1018          }
1019  
1020          return false;
1021      };
1022  
1023      Util.StorageManager.register(StorageEngineGears);
1024      Util.StorageEngineGears = StorageEngineGears;
1025  }());
1026  /*
1027   * SWF limitation:
1028   *     - only 100,000 bytes of data may be stored this way
1029   *  - data is publicly available on user machine
1030   *
1031   * Thoughts:
1032   *  - data can be shared across browsers
1033   *  - how can we not use cookies to handle session location
1034   */
1035  (function() {
1036      // internal shorthand
1037  var Y = YAHOO,
1038      Util = Y.util,
1039      Lang = Y.lang,
1040      Dom = Util.Dom,
1041      StorageManager = Util.StorageManager,
1042      
1043      /*
1044       * The minimum width required to be able to display the settings panel within the SWF.
1045       */    
1046      MINIMUM_WIDTH = 215,
1047  
1048      /*
1049       * The minimum height required to be able to display the settings panel within the SWF.
1050       */    
1051      MINIMUM_HEIGHT = 138,
1052  
1053      RX_STORAGE_PREFIX = new RegExp('^(' + StorageManager.LOCATION_SESSION + '|' + StorageManager.LOCATION_LOCAL + ')'),
1054  
1055      // local variables
1056      _driver = null,
1057  
1058      /*
1059       * Creates a location bound key.
1060       */
1061      _getKey = function(that, sKey) {
1062          return that._location + sKey;
1063      },
1064  
1065      /*
1066       * Initializes the engine, if it isn't already initialized.
1067       */
1068      _initDriver = function(oCfg) {
1069          if (! _driver) {
1070              if (! Lang.isString(oCfg.swfURL)) {oCfg.swfURL = StorageEngineSWF.SWFURL;}
1071              if (! oCfg.containerID) {
1072                  var bd = document.getElementsByTagName('body')[0],
1073                      container = bd.appendChild(document.createElement('div'));
1074                  oCfg.containerID = Dom.generateId(container);
1075              }
1076  
1077              if (! oCfg.attributes) {oCfg.attributes  = {};}
1078              if (! oCfg.attributes.flashVars) {oCfg.attributes.flashVars = {};}
1079              oCfg.attributes.flashVars.allowedDomain = document.location.hostname;
1080              oCfg.attributes.flashVars.useCompression = 'true';
1081              oCfg.attributes.version = 9.115;
1082              _driver = new Y.widget.SWF(oCfg.containerID, oCfg.swfURL, oCfg.attributes);
1083  
1084              // subscribe to save for info
1085              _driver.subscribe('save', function(o) {
1086                  Y.log(o.message, 'info');
1087              });
1088  
1089              // subscribe to errors
1090              _driver.subscribe('quotaExceededError', function(o) {
1091                  Y.log(o.message, 'error');
1092              });
1093              _driver.subscribe('inadequateDimensions', function(o) {
1094                  Y.log(o.message, 'error');
1095              });
1096              _driver.subscribe('error', function(o) {
1097                  Y.log(o.message, 'error');
1098              });
1099              _driver.subscribe('securityError', function(o) {
1100                  Y.log(o.message, 'error');
1101              });
1102          }
1103      },
1104  
1105      /**
1106       * The StorageEngineSWF class implements the SWF storage engine.
1107       * @namespace YAHOO.util
1108       * @class StorageEngineSWF
1109       * @uses YAHOO.widget.SWF
1110       * @constructor
1111       * @extend YAHOO.util.Storage
1112       * @param sLocation {String} Required. The storage location.
1113       * @param oConf {Object} Required. A configuration object.
1114       */
1115      StorageEngineSWF = function(sLocation, oConf) {
1116          var that = this;
1117          StorageEngineSWF.superclass.constructor.call(that, sLocation, StorageEngineSWF.ENGINE_NAME, oConf);
1118          
1119          _initDriver(that._cfg);
1120          
1121          var _onContentReady = function() {
1122              that._swf = _driver._swf;
1123              _driver.initialized = true;
1124              
1125              var isSessionStorage = StorageManager.LOCATION_SESSION === that._location,
1126                  sessionKey = Util.Cookie.get('sessionKey' + StorageEngineSWF.ENGINE_NAME),
1127                  i, key, isKeySessionStorage;
1128  
1129              for (i = _driver.callSWF("getLength", []) - 1; 0 <= i; i -= 1) {
1130                  key = _driver.callSWF("getNameAt", [i]);
1131                  isKeySessionStorage = isSessionStorage && (-1 < key.indexOf(StorageManager.LOCATION_SESSION));
1132  
1133                  // this is session storage, but the session key is not set, so remove item
1134                  if (isKeySessionStorage && ! sessionKey) {
1135                      _driver.callSWF("removeItem", [key]);
1136                  }
1137                  else if (isSessionStorage === isKeySessionStorage) {
1138                      // the key matches the storage type, add to key collection
1139                      that._addKey(key);
1140                  }
1141              }
1142  
1143              // this is session storage, ensure that the session key is set
1144              if (isSessionStorage) {
1145                  Util.Cookie.set('sessionKey' + StorageEngineSWF.ENGINE_NAME, true);
1146              }
1147  
1148              that.fireEvent(Util.Storage.CE_READY);
1149          };
1150          
1151          // evaluate immediately, SWF is already loaded
1152          if (_driver.initialized) {
1153              _onContentReady();
1154          }
1155          else {
1156              // evaluates when the SWF is loaded
1157              _driver.addListener("contentReady", _onContentReady);
1158          }
1159      };
1160  
1161      Lang.extend(StorageEngineSWF, Util.StorageEngineKeyed, {
1162          /**
1163           * The underlying SWF of the engine, exposed so developers can modify the adapter behavior.
1164           * @property _swf
1165           * @type {Object}
1166           * @protected
1167           */
1168          _swf: null,
1169  
1170          /*
1171           * Implementation to clear the values from the storage engine.
1172           * @see YAHOO.util.Storage._clear
1173           */
1174          _clear: function() {
1175              for (var i = this._keys.length - 1, sKey; 0 <= i; i -= 1) {
1176                  sKey = this._keys[i];
1177                  _driver.callSWF("removeItem", [sKey]);
1178              }
1179              // since keys are used to clear, we call the super function second
1180              StorageEngineSWF.superclass._clear.call(this);
1181          },
1182  
1183          /*
1184           * Implementation to fetch an item from the storage engine.
1185           * @see YAHOO.util.Storage._getItem
1186           */
1187          _getItem: function(sKey) {
1188              var sLocationKey = _getKey(this, sKey);
1189              return _driver.callSWF("getValueOf", [sLocationKey]);
1190          },
1191  
1192          /*
1193           * Implementation to fetch a key from the storage engine.
1194           * @see YAHOO.util.Storage.key
1195           */
1196          _key: function(index) {
1197              return StorageEngineSWF.superclass._key.call(this, index).replace(RX_STORAGE_PREFIX, '');
1198          },
1199  
1200          /*
1201           * Implementation to remove an item from the storage engine.
1202           * @see YAHOO.util.Storage._removeItem
1203           */
1204          _removeItem: function(sKey) {
1205              Y.log("removing SWF key: " + sKey);
1206              var sLocationKey = _getKey(this, sKey);
1207              StorageEngineSWF.superclass._removeItem.call(this, sLocationKey);
1208              _driver.callSWF("removeItem", [sLocationKey]);
1209          },
1210  
1211          /*
1212           * Implementation to remove an item from the storage engine.
1213           * @see YAHOO.util.Storage._setItem
1214           */
1215          _setItem: function(sKey, oData) {
1216              var sLocationKey = _getKey(this, sKey), swfNode;
1217  
1218              if (_driver.callSWF("setItem", [sLocationKey, oData])) {
1219                  this._addKey(sLocationKey);
1220                  return true;
1221              }
1222              else {
1223                  /*
1224                      note:
1225                          right if the FLASH SLO size needs to be adjusted, then this request and all future requests fail
1226                          should we queue these up and poll for when there is enough space?
1227                   */
1228                  swfNode = Dom.get(_driver._id);
1229                  if (MINIMUM_WIDTH > Dom.getStyle(swfNode, 'width').replace(/\D+/g, '')) {Dom.setStyle(swfNode, 'width', MINIMUM_WIDTH + 'px');}
1230                  if (MINIMUM_HEIGHT > Dom.getStyle(swfNode, 'height').replace(/\D+/g, '')) {Dom.setStyle(swfNode, 'height', MINIMUM_HEIGHT + 'px');}
1231                  Y.log("attempting to show settings. are dimensions adequate? " + _driver.callSWF("hasAdequateDimensions"));
1232                  return _driver.callSWF("displaySettings", []);
1233              }
1234          }
1235      });
1236  
1237      StorageEngineSWF.SWFURL = "swfstore.swf";
1238      StorageEngineSWF.ENGINE_NAME = 'swf';
1239  
1240      StorageEngineSWF.isAvailable = function() {
1241          return (6 <= Y.env.ua.flash && Y.widget.SWF);
1242      };
1243  
1244      StorageManager.register(StorageEngineSWF);
1245      Util.StorageEngineSWF = StorageEngineSWF;
1246  }());
1247  YAHOO.register("storage", YAHOO.util.Storage, {version: "2.9.0", build: "2800"});
1248  
1249  }, '2.9.0' ,{"requires": ["yui2-yahoo", "yui2-event", "yui2-cookie"], "optional": ["yui2-dom", "yui2-element", "yui2-swf", "yui2-swfstore"]});


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1