[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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"]});
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |