diff --git a/ajax/libs/jStorage/0.1.6.1/jstorage.js b/ajax/libs/jStorage/0.1.6.1/jstorage.js new file mode 100644 index 000000000..f05a6decc --- /dev/null +++ b/ajax/libs/jStorage/0.1.6.1/jstorage.js @@ -0,0 +1,518 @@ +/* + * ----------------------------- JSTORAGE ------------------------------------- + * Simple local storage wrapper to save data on the browser side, supporting + * all major browsers - IE6+, Firefox2+, Safari4+, Chrome4+ and Opera 10.5+ + * + * Copyright (c) 2010 Andris Reinman, andris.reinman@gmail.com + * Project homepage: www.jstorage.info + * + * Licensed under MIT-style license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * $.jStorage + * + * USAGE: + * + * jStorage requires Prototype, MooTools or jQuery! If jQuery is used, then + * jQuery-JSON (http://code.google.com/p/jquery-json/) is also needed. + * (jQuery-JSON needs to be loaded BEFORE jStorage!) + * + * Methods: + * + * -set(key, value) + * $.jStorage.set(key, value) -> saves a value + * + * -get(key[, default]) + * value = $.jStorage.get(key [, default]) -> + * retrieves value if key exists, or default if it doesn't + * + * -deleteKey(key) + * $.jStorage.deleteKey(key) -> removes a key from the storage + * + * -flush() + * $.jStorage.flush() -> clears the cache + * + * -storageObj() + * $.jStorage.storageObj() -> returns a read-ony copy of the actual storage + * + * -storageSize() + * $.jStorage.storageSize() -> returns the size of the storage in bytes + * + * -index() + * $.jStorage.index() -> returns the used keys as an array + * + * -storageAvailable() + * $.jStorage.storageAvailable() -> returns true if storage is available + * + * -reInit() + * $.jStorage.reInit() -> reloads the data from browser storage + * + * can be any JSON-able value, including objects and arrays. + * + **/ + +(function($){ + if(!$ || !($.toJSON || Object.toJSON || window.JSON)){ + throw new Error("jQuery, MooTools or Prototype needs to be loaded before jStorage!"); + } + + var + /* This is the object, that holds the cached values */ + _storage = {}, + + /* Actual browser storage (localStorage or globalStorage['domain']) */ + _storage_service = {jStorage:"{}"}, + + /* DOM element for older IE versions, holds userData behavior */ + _storage_elm = null, + + /* How much space does the storage take */ + _storage_size = 0, + + /* function to encode objects to JSON strings */ + json_encode = $.toJSON || Object.toJSON || (window.JSON && (JSON.encode || JSON.stringify)), + + /* function to decode objects from JSON strings */ + json_decode = $.evalJSON || (window.JSON && (JSON.decode || JSON.parse)) || function(str){ + return String(str).evalJSON(); + }, + + /* which backend is currently used */ + _backend = false, + + /* Next check for TTL */ + _ttl_timeout, + + /** + * XML encoding and decoding as XML nodes can't be JSON'ized + * XML nodes are encoded and decoded if the node is the value to be saved + * but not if it's as a property of another object + * Eg. - + * $.jStorage.set("key", xmlNode); // IS OK + * $.jStorage.set("key", {xml: xmlNode}); // NOT OK + */ + _XMLService = { + + /** + * Validates a XML node to be XML + * based on jQuery.isXML function + */ + isXML: function(elm){ + var documentElement = (elm ? elm.ownerDocument || elm : 0).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; + }, + + /** + * Encodes a XML node to string + * based on http://www.mercurytide.co.uk/news/article/issues-when-working-ajax/ + */ + encode: function(xmlNode) { + if(!this.isXML(xmlNode)){ + return false; + } + try{ // Mozilla, Webkit, Opera + return new XMLSerializer().serializeToString(xmlNode); + }catch(E1) { + try { // IE + return xmlNode.xml; + }catch(E2){} + } + return false; + }, + + /** + * Decodes a XML node from string + * loosely based on http://outwestmedia.com/jquery-plugins/xmldom/ + */ + decode: function(xmlString){ + var dom_parser = ("DOMParser" in window && (new DOMParser()).parseFromString) || + (window.ActiveXObject && function(_xmlString) { + var xml_doc = new ActiveXObject('Microsoft.XMLDOM'); + xml_doc.async = 'false'; + xml_doc.loadXML(_xmlString); + return xml_doc; + }), + resultXML; + if(!dom_parser){ + return false; + } + resultXML = dom_parser.call("DOMParser" in window && (new DOMParser()) || window, xmlString, 'text/xml'); + return this.isXML(resultXML)?resultXML:false; + } + }; + + ////////////////////////// PRIVATE METHODS //////////////////////// + + /** + * Initialization function. Detects if the browser supports DOM Storage + * or userData behavior and behaves accordingly. + * @returns undefined + */ + function _init(){ + /* Check if browser supports localStorage */ + var localStorageReallyWorks = false; + if("localStorage" in window){ + try { + window.localStorage.setItem('_tmptest', 'tmpval'); + localStorageReallyWorks = true; + window.localStorage.removeItem('_tmptest'); + } catch(BogusQuotaExceededErrorOnIos5) { + // Thanks be to iOS5 Private Browsing mode which throws + // QUOTA_EXCEEDED_ERRROR DOM Exception 22. + } + } + if(localStorageReallyWorks){ + try { + if(window.localStorage) { + _storage_service = window.localStorage; + _backend = "localStorage"; + } + } catch(E3) {/* Firefox fails when touching localStorage and cookies are disabled */} + } + /* Check if browser supports globalStorage */ + else if("globalStorage" in window){ + try { + if(window.globalStorage) { + _storage_service = window.globalStorage[window.location.hostname]; + _backend = "globalStorage"; + } + } catch(E4) {/* Firefox fails when touching localStorage and cookies are disabled */} + } + /* Check if browser supports userData behavior */ + else { + _storage_elm = document.createElement('link'); + if(_storage_elm.addBehavior){ + + /* Use a DOM element to act as userData storage */ + _storage_elm.style.behavior = 'url(#default#userData)'; + + /* userData element needs to be inserted into the DOM! */ + document.getElementsByTagName('head')[0].appendChild(_storage_elm); + + _storage_elm.load("jStorage"); + var data = "{}"; + try{ + data = _storage_elm.getAttribute("jStorage"); + }catch(E5){} + _storage_service.jStorage = data; + _backend = "userDataBehavior"; + }else{ + _storage_elm = null; + return; + } + } + + _load_storage(); + + // remove dead keys + _handleTTL(); + } + + /** + * Loads the data from the storage based on the supported mechanism + * @returns undefined + */ + function _load_storage(){ + /* if jStorage string is retrieved, then decode it */ + if(_storage_service.jStorage){ + try{ + _storage = json_decode(String(_storage_service.jStorage)); + }catch(E6){_storage_service.jStorage = "{}";} + }else{ + _storage_service.jStorage = "{}"; + } + _storage_size = _storage_service.jStorage?String(_storage_service.jStorage).length:0; + } + + /** + * This functions provides the "save" mechanism to store the jStorage object + * @returns undefined + */ + function _save(){ + try{ + _storage_service.jStorage = json_encode(_storage); + // If userData is used as the storage engine, additional + if(_storage_elm) { + _storage_elm.setAttribute("jStorage",_storage_service.jStorage); + _storage_elm.save("jStorage"); + } + _storage_size = _storage_service.jStorage?String(_storage_service.jStorage).length:0; + }catch(E7){/* probably cache is full, nothing is saved this way*/} + } + + /** + * Function checks if a key is set and is string or numberic + */ + function _checkKey(key){ + if(!key || (typeof key != "string" && typeof key != "number")){ + throw new TypeError('Key name must be string or numeric'); + } + if(key == "__jstorage_meta"){ + throw new TypeError('Reserved key name'); + } + return true; + } + + /** + * Removes expired keys + */ + function _handleTTL(){ + var curtime, i, TTL, nextExpire = Infinity, changed = false; + + clearTimeout(_ttl_timeout); + + if(!_storage.__jstorage_meta || typeof _storage.__jstorage_meta.TTL != "object"){ + // nothing to do here + return; + } + + curtime = +new Date(); + TTL = _storage.__jstorage_meta.TTL; + for(i in TTL){ + if(TTL.hasOwnProperty(i)){ + if(TTL[i] <= curtime){ + delete TTL[i]; + delete _storage[i]; + changed = true; + }else if(TTL[i] < nextExpire){ + nextExpire = TTL[i]; + } + } + } + + // set next check + if(nextExpire != Infinity){ + _ttl_timeout = setTimeout(_handleTTL, nextExpire - curtime); + } + + // save changes + if(changed){ + _save(); + } + } + + ////////////////////////// PUBLIC INTERFACE ///////////////////////// + + $.jStorage = { + /* Version number */ + version: "0.1.6.1", + + /** + * Sets a key's value. + * + * @param {String} key - Key to set. If this value is not set or not + * a string an exception is raised. + * @param value - Value to set. This can be any value that is JSON + * compatible (Numbers, Strings, Objects etc.). + * @returns the used value + */ + set: function(key, value){ + _checkKey(key); + if(_XMLService.isXML(value)){ + value = {_is_xml:true,xml:_XMLService.encode(value)}; + }else if(typeof value == "function"){ + value = null; // functions can't be saved! + }else if(value && typeof value == "object"){ + // clone the object before saving to _storage tree + value = json_decode(json_encode(value)); + } + _storage[key] = value; + _save(); + return value; + }, + + /** + * Looks up a key in cache + * + * @param {String} key - Key to look up. + * @param {mixed} def - Default value to return, if key didn't exist. + * @returns the key value, default value or + */ + get: function(key, def){ + _checkKey(key); + if(key in _storage){ + if(_storage[key] && typeof _storage[key] == "object" && + _storage[key]._is_xml && + _storage[key]._is_xml){ + return _XMLService.decode(_storage[key].xml); + }else{ + return _storage[key]; + } + } + return typeof(def) == 'undefined' ? null : def; + }, + + /** + * Deletes a key from cache. + * + * @param {String} key - Key to delete. + * @returns true if key existed or false if it didn't + */ + deleteKey: function(key){ + _checkKey(key); + if(key in _storage){ + delete _storage[key]; + // remove from TTL list + if(_storage.__jstorage_meta && + typeof _storage.__jstorage_meta.TTL == "object" && + key in _storage.__jstorage_meta.TTL){ + delete _storage.__jstorage_meta.TTL[key]; + } + _save(); + return true; + } + return false; + }, + + /** + * Sets a TTL for a key, or remove it if ttl value is 0 or below + * + * @param {String} key - key to set the TTL for + * @param {Number} ttl - TTL timeout in milliseconds + * @returns true if key existed or false if it didn't + */ + setTTL: function(key, ttl){ + var curtime = +new Date(); + _checkKey(key); + ttl = Number(ttl) || 0; + if(key in _storage){ + + if(!_storage.__jstorage_meta){ + _storage.__jstorage_meta = {}; + } + if(!_storage.__jstorage_meta.TTL){ + _storage.__jstorage_meta.TTL = {}; + } + + // Set TTL value for the key + if(ttl>0){ + _storage.__jstorage_meta.TTL[key] = curtime + ttl; + }else{ + delete _storage.__jstorage_meta.TTL[key]; + } + + _save(); + + _handleTTL(); + return true; + } + return false; + }, + + /** + * Deletes everything in cache. + * + * @return true + */ + flush: function(){ + _storage = {}; + _save(); + return true; + }, + + /** + * Returns a read-only copy of _storage + * + * @returns Object + */ + storageObj: function(){ + function F() {} + F.prototype = _storage; + return new F(); + }, + + /** + * Returns an index of all used keys as an array + * ['key1', 'key2',..'keyN'] + * + * @returns Array + */ + index: function(){ + var index = [], i; + for(i in _storage){ + if(_storage.hasOwnProperty(i) && i != "__jstorage_meta"){ + index.push(i); + } + } + return index; + }, + + /** + * How much space in bytes does the storage take? + * + * @returns Number + */ + storageSize: function(){ + return _storage_size; + }, + + /** + * Which backend is currently in use? + * + * @returns String + */ + currentBackend: function(){ + return _backend; + }, + + /** + * Test if storage is available + * + * @returns Boolean + */ + storageAvailable: function(){ + return !!_backend; + }, + + /** + * Reloads the data from browser storage + * + * @returns undefined + */ + reInit: function(){ + var new_storage_elm, data; + if(_storage_elm && _storage_elm.addBehavior){ + new_storage_elm = document.createElement('link'); + + _storage_elm.parentNode.replaceChild(new_storage_elm, _storage_elm); + _storage_elm = new_storage_elm; + + /* Use a DOM element to act as userData storage */ + _storage_elm.style.behavior = 'url(#default#userData)'; + + /* userData element needs to be inserted into the DOM! */ + document.getElementsByTagName('head')[0].appendChild(_storage_elm); + + _storage_elm.load("jStorage"); + data = "{}"; + try{ + data = _storage_elm.getAttribute("jStorage"); + }catch(E5){} + _storage_service.jStorage = data; + _backend = "userDataBehavior"; + } + + _load_storage(); + } + }; + + // Initialize jStorage + _init(); + +})(window.jQuery || window.$); \ No newline at end of file diff --git a/ajax/libs/jStorage/0.1.6.1/jstorage.min.js b/ajax/libs/jStorage/0.1.6.1/jstorage.min.js new file mode 100644 index 000000000..fe7243f97 --- /dev/null +++ b/ajax/libs/jStorage/0.1.6.1/jstorage.min.js @@ -0,0 +1,8 @@ +(function(g){function m(){if(e.jStorage)try{c=n(""+e.jStorage)}catch(a){e.jStorage="{}"}else e.jStorage="{}";j=e.jStorage?(""+e.jStorage).length:0}function h(){try{e.jStorage=o(c),d&&(d.setAttribute("jStorage",e.jStorage),d.save("jStorage")),j=e.jStorage?(""+e.jStorage).length:0}catch(a){}}function i(a){if(!a||"string"!=typeof a&&"number"!=typeof a)throw new TypeError("Key name must be string or numeric");if("__jstorage_meta"==a)throw new TypeError("Reserved key name");return!0}function k(){var a, +b,d,e=Infinity,f=!1;clearTimeout(p);if(c.__jstorage_meta&&"object"==typeof c.__jstorage_meta.TTL){a=+new Date;d=c.__jstorage_meta.TTL;for(b in d)d.hasOwnProperty(b)&&(d[b]<=a?(delete d[b],delete c[b],f=!0):d[b]