[ 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 StorageEngineGears.superclass._removeItem.call(this, sKey); 956 _driver.execute('BEGIN'); 957 _driver.execute('DELETE FROM ' + TABLE_NAME + ' WHERE key="' + eURI(sKey) + '" AND location="' + eURI(this._location) + '"'); 958 _driver.execute('COMMIT'); 959 }, 960 961 /* 962 * Implementation to remove an item from the storage engine. 963 * @see YAHOO.util.Storage._setItem 964 */ 965 _setItem: function(sKey, oData) { 966 967 this._addKey(sKey); 968 969 var sEscapedKey = eURI(sKey), 970 sEscapedLocation = eURI(this._location), 971 sEscapedValue = eURI(oData), // escaped twice, maybe not necessary 972 aValues = [], 973 nLen = SQL_STMT_LIMIT - (sEscapedKey + sEscapedLocation).length, 974 i=0, j; 975 976 // the length of the value exceeds the available space 977 if (nLen < sEscapedValue.length) { 978 for (j = sEscapedValue.length; i < j; i += nLen) { 979 aValues.push(sEscapedValue.substr(i, nLen)); 980 } 981 } else { 982 aValues.push(sEscapedValue); 983 } 984 985 // Google recommends using INSERT instead of update, because it is faster 986 _driver.execute('BEGIN'); 987 _driver.execute('DELETE FROM ' + TABLE_NAME + ' WHERE key="' + sEscapedKey + '" AND location="' + sEscapedLocation + '"'); 988 for (i = 0, j = aValues.length; i < j; i += 1) { 989 _driver.execute('INSERT INTO ' + TABLE_NAME + ' VALUES ("' + sEscapedKey + '", "' + sEscapedLocation + '", "' + aValues[i] + '")'); 990 } 991 _driver.execute('COMMIT'); 992 993 return true; 994 } 995 }); 996 997 // releases the engine when the page unloads 998 Util.Event.on('unload', function() { 999 if (_driver) {_driver.close();} 1000 }); 1001 1002 StorageEngineGears.ENGINE_NAME = 'gears'; 1003 StorageEngineGears.GEARS = 'beta.database'; 1004 StorageEngineGears.DATABASE = 'yui.database'; 1005 1006 StorageEngineGears.isAvailable = function() { 1007 if (('google' in window) && ('gears' in window.google)) { 1008 try { 1009 // this will throw an exception if the user denies gears 1010 google.gears.factory.create(StorageEngineGears.GEARS); 1011 return true; 1012 } 1013 catch (e) { 1014 // no need to do anything 1015 } 1016 } 1017 1018 return false; 1019 }; 1020 1021 Util.StorageManager.register(StorageEngineGears); 1022 Util.StorageEngineGears = StorageEngineGears; 1023 }()); 1024 /* 1025 * SWF limitation: 1026 * - only 100,000 bytes of data may be stored this way 1027 * - data is publicly available on user machine 1028 * 1029 * Thoughts: 1030 * - data can be shared across browsers 1031 * - how can we not use cookies to handle session location 1032 */ 1033 (function() { 1034 // internal shorthand 1035 var Y = YAHOO, 1036 Util = Y.util, 1037 Lang = Y.lang, 1038 Dom = Util.Dom, 1039 StorageManager = Util.StorageManager, 1040 1041 /* 1042 * The minimum width required to be able to display the settings panel within the SWF. 1043 */ 1044 MINIMUM_WIDTH = 215, 1045 1046 /* 1047 * The minimum height required to be able to display the settings panel within the SWF. 1048 */ 1049 MINIMUM_HEIGHT = 138, 1050 1051 RX_STORAGE_PREFIX = new RegExp('^(' + StorageManager.LOCATION_SESSION + '|' + StorageManager.LOCATION_LOCAL + ')'), 1052 1053 // local variables 1054 _driver = null, 1055 1056 /* 1057 * Creates a location bound key. 1058 */ 1059 _getKey = function(that, sKey) { 1060 return that._location + sKey; 1061 }, 1062 1063 /* 1064 * Initializes the engine, if it isn't already initialized. 1065 */ 1066 _initDriver = function(oCfg) { 1067 if (! _driver) { 1068 if (! Lang.isString(oCfg.swfURL)) {oCfg.swfURL = StorageEngineSWF.SWFURL;} 1069 if (! oCfg.containerID) { 1070 var bd = document.getElementsByTagName('body')[0], 1071 container = bd.appendChild(document.createElement('div')); 1072 oCfg.containerID = Dom.generateId(container); 1073 } 1074 1075 if (! oCfg.attributes) {oCfg.attributes = {};} 1076 if (! oCfg.attributes.flashVars) {oCfg.attributes.flashVars = {};} 1077 oCfg.attributes.flashVars.allowedDomain = document.location.hostname; 1078 oCfg.attributes.flashVars.useCompression = 'true'; 1079 oCfg.attributes.version = 9.115; 1080 _driver = new Y.widget.SWF(oCfg.containerID, oCfg.swfURL, oCfg.attributes); 1081 1082 // subscribe to save for info 1083 _driver.subscribe('save', function(o) { 1084 Y.log(o.message, 'info'); 1085 }); 1086 1087 // subscribe to errors 1088 _driver.subscribe('quotaExceededError', function(o) { 1089 Y.log(o.message, 'error'); 1090 }); 1091 _driver.subscribe('inadequateDimensions', function(o) { 1092 Y.log(o.message, 'error'); 1093 }); 1094 _driver.subscribe('error', function(o) { 1095 Y.log(o.message, 'error'); 1096 }); 1097 _driver.subscribe('securityError', function(o) { 1098 Y.log(o.message, 'error'); 1099 }); 1100 } 1101 }, 1102 1103 /** 1104 * The StorageEngineSWF class implements the SWF storage engine. 1105 * @namespace YAHOO.util 1106 * @class StorageEngineSWF 1107 * @uses YAHOO.widget.SWF 1108 * @constructor 1109 * @extend YAHOO.util.Storage 1110 * @param sLocation {String} Required. The storage location. 1111 * @param oConf {Object} Required. A configuration object. 1112 */ 1113 StorageEngineSWF = function(sLocation, oConf) { 1114 var that = this; 1115 StorageEngineSWF.superclass.constructor.call(that, sLocation, StorageEngineSWF.ENGINE_NAME, oConf); 1116 1117 _initDriver(that._cfg); 1118 1119 var _onContentReady = function() { 1120 that._swf = _driver._swf; 1121 _driver.initialized = true; 1122 1123 var isSessionStorage = StorageManager.LOCATION_SESSION === that._location, 1124 sessionKey = Util.Cookie.get('sessionKey' + StorageEngineSWF.ENGINE_NAME), 1125 i, key, isKeySessionStorage; 1126 1127 for (i = _driver.callSWF("getLength", []) - 1; 0 <= i; i -= 1) { 1128 key = _driver.callSWF("getNameAt", [i]); 1129 isKeySessionStorage = isSessionStorage && (-1 < key.indexOf(StorageManager.LOCATION_SESSION)); 1130 1131 // this is session storage, but the session key is not set, so remove item 1132 if (isKeySessionStorage && ! sessionKey) { 1133 _driver.callSWF("removeItem", [key]); 1134 } 1135 else if (isSessionStorage === isKeySessionStorage) { 1136 // the key matches the storage type, add to key collection 1137 that._addKey(key); 1138 } 1139 } 1140 1141 // this is session storage, ensure that the session key is set 1142 if (isSessionStorage) { 1143 Util.Cookie.set('sessionKey' + StorageEngineSWF.ENGINE_NAME, true); 1144 } 1145 1146 that.fireEvent(Util.Storage.CE_READY); 1147 }; 1148 1149 // evaluate immediately, SWF is already loaded 1150 if (_driver.initialized) { 1151 _onContentReady(); 1152 } 1153 else { 1154 // evaluates when the SWF is loaded 1155 _driver.addListener("contentReady", _onContentReady); 1156 } 1157 }; 1158 1159 Lang.extend(StorageEngineSWF, Util.StorageEngineKeyed, { 1160 /** 1161 * The underlying SWF of the engine, exposed so developers can modify the adapter behavior. 1162 * @property _swf 1163 * @type {Object} 1164 * @protected 1165 */ 1166 _swf: null, 1167 1168 /* 1169 * Implementation to clear the values from the storage engine. 1170 * @see YAHOO.util.Storage._clear 1171 */ 1172 _clear: function() { 1173 for (var i = this._keys.length - 1, sKey; 0 <= i; i -= 1) { 1174 sKey = this._keys[i]; 1175 _driver.callSWF("removeItem", [sKey]); 1176 } 1177 // since keys are used to clear, we call the super function second 1178 StorageEngineSWF.superclass._clear.call(this); 1179 }, 1180 1181 /* 1182 * Implementation to fetch an item from the storage engine. 1183 * @see YAHOO.util.Storage._getItem 1184 */ 1185 _getItem: function(sKey) { 1186 var sLocationKey = _getKey(this, sKey); 1187 return _driver.callSWF("getValueOf", [sLocationKey]); 1188 }, 1189 1190 /* 1191 * Implementation to fetch a key from the storage engine. 1192 * @see YAHOO.util.Storage.key 1193 */ 1194 _key: function(index) { 1195 return StorageEngineSWF.superclass._key.call(this, index).replace(RX_STORAGE_PREFIX, ''); 1196 }, 1197 1198 /* 1199 * Implementation to remove an item from the storage engine. 1200 * @see YAHOO.util.Storage._removeItem 1201 */ 1202 _removeItem: function(sKey) { 1203 Y.log("removing SWF key: " + sKey); 1204 var sLocationKey = _getKey(this, sKey); 1205 StorageEngineSWF.superclass._removeItem.call(this, sLocationKey); 1206 _driver.callSWF("removeItem", [sLocationKey]); 1207 }, 1208 1209 /* 1210 * Implementation to remove an item from the storage engine. 1211 * @see YAHOO.util.Storage._setItem 1212 */ 1213 _setItem: function(sKey, oData) { 1214 var sLocationKey = _getKey(this, sKey), swfNode; 1215 1216 if (_driver.callSWF("setItem", [sLocationKey, oData])) { 1217 this._addKey(sLocationKey); 1218 return true; 1219 } 1220 else { 1221 /* 1222 note: 1223 right if the FLASH SLO size needs to be adjusted, then this request and all future requests fail 1224 should we queue these up and poll for when there is enough space? 1225 */ 1226 swfNode = Dom.get(_driver._id); 1227 if (MINIMUM_WIDTH > Dom.getStyle(swfNode, 'width').replace(/\D+/g, '')) {Dom.setStyle(swfNode, 'width', MINIMUM_WIDTH + 'px');} 1228 if (MINIMUM_HEIGHT > Dom.getStyle(swfNode, 'height').replace(/\D+/g, '')) {Dom.setStyle(swfNode, 'height', MINIMUM_HEIGHT + 'px');} 1229 Y.log("attempting to show settings. are dimensions adequate? " + _driver.callSWF("hasAdequateDimensions")); 1230 return _driver.callSWF("displaySettings", []); 1231 } 1232 } 1233 }); 1234 1235 StorageEngineSWF.SWFURL = "swfstore.swf"; 1236 StorageEngineSWF.ENGINE_NAME = 'swf'; 1237 1238 StorageEngineSWF.isAvailable = function() { 1239 return (6 <= Y.env.ua.flash && Y.widget.SWF); 1240 }; 1241 1242 StorageManager.register(StorageEngineSWF); 1243 Util.StorageEngineSWF = StorageEngineSWF; 1244 }()); 1245 YAHOO.register("storage", YAHOO.util.Storage, {version: "2.9.0", build: "2800"}); 1246 1247 }, '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 |