summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'SemanticMediaWiki/resources/jquery/jquery.jstorage.js')
-rw-r--r--SemanticMediaWiki/resources/jquery/jquery.jstorage.js1143
1 files changed, 0 insertions, 1143 deletions
diff --git a/SemanticMediaWiki/resources/jquery/jquery.jstorage.js b/SemanticMediaWiki/resources/jquery/jquery.jstorage.js
deleted file mode 100644
index 9d4ca1f8..00000000
--- a/SemanticMediaWiki/resources/jquery/jquery.jstorage.js
+++ /dev/null
@@ -1,1143 +0,0 @@
-/*
- * ----------------------------- 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 - 2012 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.
- */
-
- (function(){
- var
- /* jStorage version */
- JSTORAGE_VERSION = "0.3.2",
-
- /* detect a dollar object or create one if not found */
- $ = window.jQuery || window.$ || (window.$ = {}),
-
- /* check for a JSON handling support */
- JSON = {
- parse:
- window.JSON && (window.JSON.parse || window.JSON.decode) ||
- String.prototype.evalJSON && function(str){return String(str).evalJSON();} ||
- $.parseJSON ||
- $.evalJSON,
- stringify:
- Object.toJSON ||
- window.JSON && (window.JSON.stringify || window.JSON.encode) ||
- $.toJSON
- };
-
- // Break if no JSON support was found
- if(!JSON.parse || !JSON.stringify){
- throw new Error("No JSON support found, include //cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js to page");
- }
-
- var
- /* This is the object, that holds the cached values */
- _storage = {__jstorage_meta:{CRC32:{}}},
-
- /* 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,
-
- /* which backend is currently used */
- _backend = false,
-
- /* onchange observers */
- _observers = {},
-
- /* timeout to wait after onchange event */
- _observer_timeout = false,
-
- /* last update time */
- _observer_update = 0,
-
- /* pubsub observers */
- _pubsub_observers = {},
-
- /* skip published items older than current timestamp */
- _pubsub_last = +new Date(),
-
- /* 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;
- }
- },
-
- _localStoragePolyfillSetKey = function(){};
-
-
- ////////////////////////// PRIVATE METHODS ////////////////////////
-
- /**
- * Initialization function. Detects if the browser supports DOM Storage
- * or userData behavior and behaves accordingly.
- */
- 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";
- _observer_update = _storage_service.jStorage_update;
- }
- } 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";
- _observer_update = _storage_service.jStorage_update;
- }
- } 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);
-
- try{
- _storage_elm.load("jStorage");
- }catch(E){
- // try to reset cache
- _storage_elm.setAttribute("jStorage", "{}");
- _storage_elm.save("jStorage");
- _storage_elm.load("jStorage");
- }
-
- var data = "{}";
- try{
- data = _storage_elm.getAttribute("jStorage");
- }catch(E5){}
-
- try{
- _observer_update = _storage_elm.getAttribute("jStorage_update");
- }catch(E6){}
-
- _storage_service.jStorage = data;
- _backend = "userDataBehavior";
- }else{
- _storage_elm = null;
- return;
- }
- }
-
- // Load data from storage
- _load_storage();
-
- // remove dead keys
- _handleTTL();
-
- // create localStorage and sessionStorage polyfills if needed
- _createPolyfillStorage("local");
- _createPolyfillStorage("session");
-
- // start listening for changes
- _setupObserver();
-
- // initialize publish-subscribe service
- _handlePubSub();
-
- // handle cached navigation
- if("addEventListener" in window){
- window.addEventListener("pageshow", function(event){
- if(event.persisted){
- _storageObserver();
- }
- }, false);
- }
- }
-
- /**
- * Create a polyfill for localStorage (type="local") or sessionStorage (type="session")
- *
- * @param {String} type Either "local" or "session"
- * @param {Boolean} forceCreate If set to true, recreate the polyfill (needed with flush)
- */
- function _createPolyfillStorage(type, forceCreate){
- var _skipSave = false,
- _length = 0,
- i,
- storage,
- storage_source = {};
-
- var rand = Math.random();
-
- if(!forceCreate && typeof window[type+"Storage"] != "undefined"){
- return;
- }
-
- // Use globalStorage for localStorage if available
- if(type == "local" && window.globalStorage){
- localStorage = window.globalStorage[window.location.hostname];
- return;
- }
-
- // only IE6/7 from this point on
- if(_backend != "userDataBehavior"){
- return;
- }
-
- // Remove existing storage element if available
- if(forceCreate && window[type+"Storage"] && window[type+"Storage"].parentNode){
- window[type+"Storage"].parentNode.removeChild(window[type+"Storage"]);
- }
-
- storage = document.createElement("button");
- document.getElementsByTagName('head')[0].appendChild(storage);
-
- if(type == "local"){
- storage_source = _storage;
- }else if(type == "session"){
- _sessionStoragePolyfillUpdate();
- }
-
- for(i in storage_source){
-
- if(storage_source.hasOwnProperty(i) && i != "__jstorage_meta" && i != "length" && typeof storage_source[i] != "undefined"){
- if(!(i in storage)){
- _length++;
- }
- storage[i] = storage_source[i];
- }
- }
-
- // Polyfill API
-
- /**
- * Indicates how many keys are stored in the storage
- */
- storage.length = _length;
-
- /**
- * Returns the key of the nth stored value
- *
- * @param {Number} n Index position
- * @return {String} Key name of the nth stored value
- */
- storage.key = function(n){
- var count = 0, i;
- _sessionStoragePolyfillUpdate();
- for(i in storage_source){
- if(storage_source.hasOwnProperty(i) && i != "__jstorage_meta" && i!="length" && typeof storage_source[i] != "undefined"){
- if(count == n){
- return i;
- }
- count++;
- }
- }
- }
-
- /**
- * Returns the current value associated with the given key
- *
- * @param {String} key key name
- * @return {Mixed} Stored value
- */
- storage.getItem = function(key){
- _sessionStoragePolyfillUpdate();
- if(type == "session"){
- return storage_source[key];
- }
- return $.jStorage.get(key);
- }
-
- /**
- * Sets or updates value for a give key
- *
- * @param {String} key Key name to be updated
- * @param {String} value String value to be stored
- */
- storage.setItem = function(key, value){
- if(typeof value == "undefined"){
- return;
- }
- storage[key] = (value || "").toString();
- }
-
- /**
- * Removes key from the storage
- *
- * @param {String} key Key name to be removed
- */
- storage.removeItem = function(key){
- if(type == "local"){
- return $.jStorage.deleteKey(key);
- }
-
- storage[key] = undefined;
-
- _skipSave = true;
- if(key in storage){
- storage.removeAttribute(key);
- }
- _skipSave = false;
- }
-
- /**
- * Clear storage
- */
- storage.clear = function(){
- if(type == "session"){
- window.name = "";
- _createPolyfillStorage("session", true);
- return;
- }
- $.jStorage.flush();
- }
-
- if(type == "local"){
-
- _localStoragePolyfillSetKey = function(key, value){
- if(key == "length"){
- return;
- }
- _skipSave = true;
- if(typeof value == "undefined"){
- if(key in storage){
- _length--;
- storage.removeAttribute(key);
- }
- }else{
- if(!(key in storage)){
- _length++;
- }
- storage[key] = (value || "").toString();
- }
- storage.length = _length;
- _skipSave = false;
- }
- }
-
- function _sessionStoragePolyfillUpdate(){
- if(type != "session"){
- return;
- }
- try{
- storage_source = JSON.parse(window.name || "{}");
- }catch(E){
- storage_source = {};
- }
- }
-
- function _sessionStoragePolyfillSave(){
- if(type != "session"){
- return;
- }
- window.name = JSON.stringify(storage_source);
- };
-
- storage.attachEvent("onpropertychange", function(e){
- if(e.propertyName == "length"){
- return;
- }
-
- if(_skipSave || e.propertyName == "length"){
- return;
- }
-
- if(type == "local"){
- if(!(e.propertyName in storage_source) && typeof storage[e.propertyName] != "undefined"){
- _length ++;
- }
- }else if(type == "session"){
- _sessionStoragePolyfillUpdate();
- if(typeof storage[e.propertyName] != "undefined" && !(e.propertyName in storage_source)){
- storage_source[e.propertyName] = storage[e.propertyName];
- _length++;
- }else if(typeof storage[e.propertyName] == "undefined" && e.propertyName in storage_source){
- delete storage_source[e.propertyName];
- _length--;
- }else{
- storage_source[e.propertyName] = storage[e.propertyName];
- }
-
- _sessionStoragePolyfillSave();
- storage.length = _length;
- return;
- }
-
- $.jStorage.set(e.propertyName, storage[e.propertyName]);
- storage.length = _length;
- });
-
- window[type+"Storage"] = storage;
- }
-
- /**
- * Reload data from storage when needed
- */
- function _reloadData(){
- var data = "{}";
-
- if(_backend == "userDataBehavior"){
- _storage_elm.load("jStorage");
-
- try{
- data = _storage_elm.getAttribute("jStorage");
- }catch(E5){}
-
- try{
- _observer_update = _storage_elm.getAttribute("jStorage_update");
- }catch(E6){}
-
- _storage_service.jStorage = data;
- }
-
- _load_storage();
-
- // remove dead keys
- _handleTTL();
-
- _handlePubSub();
- }
-
- /**
- * Sets up a storage change observer
- */
- function _setupObserver(){
- if(_backend == "localStorage" || _backend == "globalStorage"){
- if("addEventListener" in window){
- window.addEventListener("storage", _storageObserver, false);
- }else{
- document.attachEvent("onstorage", _storageObserver);
- }
- }else if(_backend == "userDataBehavior"){
- setInterval(_storageObserver, 1000);
- }
- }
-
- /**
- * Fired on any kind of data change, needs to check if anything has
- * really been changed
- */
- function _storageObserver(){
- var updateTime;
- // cumulate change notifications with timeout
- clearTimeout(_observer_timeout);
- _observer_timeout = setTimeout(function(){
-
- if(_backend == "localStorage" || _backend == "globalStorage"){
- updateTime = _storage_service.jStorage_update;
- }else if(_backend == "userDataBehavior"){
- _storage_elm.load("jStorage");
- try{
- updateTime = _storage_elm.getAttribute("jStorage_update");
- }catch(E5){}
- }
-
- if(updateTime && updateTime != _observer_update){
- _observer_update = updateTime;
- _checkUpdatedKeys();
- }
-
- }, 25);
- }
-
- /**
- * Reloads the data and checks if any keys are changed
- */
- function _checkUpdatedKeys(){
- var oldCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32)),
- newCrc32List;
-
- _reloadData();
- newCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32));
-
- var key,
- updated = [],
- removed = [];
-
- for(key in oldCrc32List){
- if(oldCrc32List.hasOwnProperty(key)){
- if(!newCrc32List[key]){
- removed.push(key);
- continue;
- }
- if(oldCrc32List[key] != newCrc32List[key] && String(oldCrc32List[key]).substr(0,2) == "2."){
- updated.push(key);
- }
- }
- }
-
- for(key in newCrc32List){
- if(newCrc32List.hasOwnProperty(key)){
- if(!oldCrc32List[key]){
- updated.push(key);
- }
- }
- }
-
- _fireObservers(updated, "updated");
- _fireObservers(removed, "deleted");
- }
-
- /**
- * Fires observers for updated keys
- *
- * @param {Array|String} keys Array of key names or a key
- * @param {String} action What happened with the value (updated, deleted, flushed)
- */
- function _fireObservers(keys, action){
- keys = [].concat(keys || []);
- if(action == "flushed"){
- keys = [];
- for(var key in _observers){
- if(_observers.hasOwnProperty(key)){
- keys.push(key);
- }
- }
- action = "deleted";
- }
- for(var i=0, len = keys.length; i<len; i++){
- if(_observers[keys[i]]){
- for(var j=0, jlen = _observers[keys[i]].length; j<jlen; j++){
- _observers[keys[i]][j](keys[i], action);
- }
- }
- }
- }
-
- /**
- * Publishes key change to listeners
- */
- function _publishChange(){
- var updateTime = (+new Date()).toString();
-
- if(_backend == "localStorage" || _backend == "globalStorage"){
- _storage_service.jStorage_update = updateTime;
- }else if(_backend == "userDataBehavior"){
- _storage_elm.setAttribute("jStorage_update", updateTime);
- _storage_elm.save("jStorage");
- }
-
- _storageObserver();
- }
-
- /**
- * Loads the data from the storage based on the supported mechanism
- */
- function _load_storage(){
- /* if jStorage string is retrieved, then decode it */
- if(_storage_service.jStorage){
- try{
- _storage = JSON.parse(String(_storage_service.jStorage));
- }catch(E6){_storage_service.jStorage = "{}";}
- }else{
- _storage_service.jStorage = "{}";
- }
- _storage_size = _storage_service.jStorage?String(_storage_service.jStorage).length:0;
-
- if(!_storage.__jstorage_meta){
- _storage.__jstorage_meta = {};
- }
- if(!_storage.__jstorage_meta.CRC32){
- _storage.__jstorage_meta.CRC32 = {};
- }
- }
-
- /**
- * This functions provides the "save" mechanism to store the jStorage object
- */
- function _save(){
- _dropOldEvents(); // remove expired events
- try{
- _storage_service.jStorage = JSON.stringify(_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
- *
- * @param {String} key Key name
- */
- 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, CRC32, nextExpire = Infinity, changed = false, deleted = [];
-
- 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;
-
- CRC32 = _storage.__jstorage_meta.CRC32;
- for(i in TTL){
- if(TTL.hasOwnProperty(i)){
- if(TTL[i] <= curtime){
- delete TTL[i];
- delete CRC32[i];
- delete _storage[i];
- changed = true;
- deleted.push(i);
- }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();
- _publishChange();
- _fireObservers(deleted, "deleted");
- }
- }
-
- /**
- * Checks if there's any events on hold to be fired to listeners
- */
- function _handlePubSub(){
- if(!_storage.__jstorage_meta.PubSub){
- return;
- }
- var pubelm,
- _pubsubCurrent = _pubsub_last;
-
- for(var i=len=_storage.__jstorage_meta.PubSub.length-1; i>=0; i--){
- pubelm = _storage.__jstorage_meta.PubSub[i];
- if(pubelm[0] > _pubsub_last){
- _pubsubCurrent = pubelm[0];
- _fireSubscribers(pubelm[1], pubelm[2]);
- }
- }
-
- _pubsub_last = _pubsubCurrent;
- }
-
- /**
- * Fires all subscriber listeners for a pubsub channel
- *
- * @param {String} channel Channel name
- * @param {Mixed} payload Payload data to deliver
- */
- function _fireSubscribers(channel, payload){
- if(_pubsub_observers[channel]){
- for(var i=0, len = _pubsub_observers[channel].length; i<len; i++){
- // send immutable data that can't be modified by listeners
- _pubsub_observers[channel][i](channel, JSON.parse(JSON.stringify(payload)));
- }
- }
- }
-
- /**
- * Remove old events from the publish stream (at least 2sec old)
- */
- function _dropOldEvents(){
- if(!_storage.__jstorage_meta.PubSub){
- return;
- }
-
- var retire = +new Date() - 2000;
-
- for(var i=0, len = _storage.__jstorage_meta.PubSub.length; i<len; i++){
- if(_storage.__jstorage_meta.PubSub[i][0] <= retire){
- // deleteCount is needed for IE6
- _storage.__jstorage_meta.PubSub.splice(i, _storage.__jstorage_meta.PubSub.length - i);
- break;
- }
- }
-
- if(!_storage.__jstorage_meta.PubSub.length){
- delete _storage.__jstorage_meta.PubSub;
- }
-
- }
-
- /**
- * Publish payload to a channel
- *
- * @param {String} channel Channel name
- * @param {Mixed} payload Payload to send to the subscribers
- */
- function _publish(channel, payload){
- if(!_storage.__jstorage_meta){
- _storage.__jstorage_meta = {};
- }
- if(!_storage.__jstorage_meta.PubSub){
- _storage.__jstorage_meta.PubSub = [];
- }
-
- _storage.__jstorage_meta.PubSub.unshift([+new Date, channel, payload]);
-
- _save();
- _publishChange();
- }
-
-
- /**
- * JS Implementation of MurmurHash2
- *
- * SOURCE: https://github.com/garycourt/murmurhash-js (MIT licensed)
- *
- * @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
- * @see http://github.com/garycourt/murmurhash-js
- * @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
- * @see http://sites.google.com/site/murmurhash/
- *
- * @param {string} str ASCII only
- * @param {number} seed Positive integer only
- * @return {number} 32-bit positive integer hash
- */
-
- function murmurhash2_32_gc(str, seed) {
- var
- l = str.length,
- h = seed ^ l,
- i = 0,
- k;
-
- while (l >= 4) {
- k =
- ((str.charCodeAt(i) & 0xff)) |
- ((str.charCodeAt(++i) & 0xff) << 8) |
- ((str.charCodeAt(++i) & 0xff) << 16) |
- ((str.charCodeAt(++i) & 0xff) << 24);
-
- k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
- k ^= k >>> 24;
- k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
-
- h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k;
-
- l -= 4;
- ++i;
- }
-
- switch (l) {
- case 3: h ^= (str.charCodeAt(i + 2) & 0xff) << 16;
- case 2: h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
- case 1: h ^= (str.charCodeAt(i) & 0xff);
- h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
- }
-
- h ^= h >>> 13;
- h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
- h ^= h >>> 15;
-
- return h >>> 0;
- }
-
- ////////////////////////// PUBLIC INTERFACE /////////////////////////
-
- $.jStorage = {
- /* Version number */
- version: JSTORAGE_VERSION,
-
- /**
- * 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 {Mixed} value Value to set. This can be any value that is JSON
- * compatible (Numbers, Strings, Objects etc.).
- * @param {Object} [options] - possible options to use
- * @param {Number} [options.TTL] - optional TTL value
- * @return {Mixed} the used value
- */
- set: function(key, value, options){
- _checkKey(key);
-
- options = options || {};
-
- // undefined values are deleted automatically
- if(typeof value == "undefined"){
- this.deleteKey(key);
- return value;
- }
-
- if(_XMLService.isXML(value)){
- value = {_is_xml:true,xml:_XMLService.encode(value)};
- }else if(typeof value == "function"){
- return undefined; // functions can't be saved!
- }else if(value && typeof value == "object"){
- // clone the object before saving to _storage tree
- value = JSON.parse(JSON.stringify(value));
- }
-
- _storage[key] = value;
-
- _storage.__jstorage_meta.CRC32[key] = "2."+murmurhash2_32_gc(JSON.stringify(value));
-
- this.setTTL(key, options.TTL || 0); // also handles saving and _publishChange
-
- _localStoragePolyfillSetKey(key, value);
-
- _fireObservers(key, "updated");
- 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.
- * @return {Mixed} the key value, default value or null
- */
- get: function(key, def){
- _checkKey(key);
- if(key in _storage){
- if(_storage[key] && typeof _storage[key] == "object" && _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.
- * @return {Boolean} 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(typeof _storage.__jstorage_meta.TTL == "object" &&
- key in _storage.__jstorage_meta.TTL){
- delete _storage.__jstorage_meta.TTL[key];
- }
-
- delete _storage.__jstorage_meta.CRC32[key];
- _localStoragePolyfillSetKey(key, undefined);
-
- _save();
- _publishChange();
- _fireObservers(key, "deleted");
- 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
- * @return {Boolean} 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.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();
-
- _publishChange();
- return true;
- }
- return false;
- },
-
- /**
- * Gets remaining TTL (in milliseconds) for a key or 0 when no TTL has been set
- *
- * @param {String} key Key to check
- * @return {Number} Remaining TTL in milliseconds
- */
- getTTL: function(key){
- var curtime = +new Date(), ttl;
- _checkKey(key);
- if(key in _storage && _storage.__jstorage_meta.TTL && _storage.__jstorage_meta.TTL[key]){
- ttl = _storage.__jstorage_meta.TTL[key] - curtime;
- return ttl || 0;
- }
- return 0;
- },
-
- /**
- * Deletes everything in cache.
- *
- * @return {Boolean} Always true
- */
- flush: function(){
- _storage = {__jstorage_meta:{CRC32:{}}};
- _createPolyfillStorage("local", true);
- _save();
- _publishChange();
- _fireObservers(null, "flushed");
- return true;
- },
-
- /**
- * Returns a read-only copy of _storage
- *
- * @return {Object} Read-only copy of _storage
- */
- storageObj: function(){
- function F() {}
- F.prototype = _storage;
- return new F();
- },
-
- /**
- * Returns an index of all used keys as an array
- * ['key1', 'key2',..'keyN']
- *
- * @return {Array} Used keys
- */
- 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?
- *
- * @return {Number} Storage size in chars (not the same as in bytes,
- * since some chars may take several bytes)
- */
- storageSize: function(){
- return _storage_size;
- },
-
- /**
- * Which backend is currently in use?
- *
- * @return {String} Backend name
- */
- currentBackend: function(){
- return _backend;
- },
-
- /**
- * Test if storage is available
- *
- * @return {Boolean} True if storage can be used
- */
- storageAvailable: function(){
- return !!_backend;
- },
-
- /**
- * Register change listeners
- *
- * @param {String} key Key name
- * @param {Function} callback Function to run when the key changes
- */
- listenKeyChange: function(key, callback){
- _checkKey(key);
- if(!_observers[key]){
- _observers[key] = [];
- }
- _observers[key].push(callback);
- },
-
- /**
- * Remove change listeners
- *
- * @param {String} key Key name to unregister listeners against
- * @param {Function} [callback] If set, unregister the callback, if not - unregister all
- */
- stopListening: function(key, callback){
- _checkKey(key);
-
- if(!_observers[key]){
- return;
- }
-
- if(!callback){
- delete _observers[key];
- return;
- }
-
- for(var i = _observers[key].length - 1; i>=0; i--){
- if(_observers[key][i] == callback){
- _observers[key].splice(i,1);
- }
- }
- },
-
- /**
- * Subscribe to a Publish/Subscribe event stream
- *
- * @param {String} channel Channel name
- * @param {Function} callback Function to run when the something is published to the channel
- */
- subscribe: function(channel, callback){
- channel = (channel || "").toString();
- if(!channel){
- throw new TypeError('Channel not defined');
- }
- if(!_pubsub_observers[channel]){
- _pubsub_observers[channel] = [];
- }
- _pubsub_observers[channel].push(callback);
- },
-
- /**
- * Publish data to an event stream
- *
- * @param {String} channel Channel name
- * @param {Mixed} payload Payload to deliver
- */
- publish: function(channel, payload){
- channel = (channel || "").toString();
- if(!channel){
- throw new TypeError('Channel not defined');
- }
-
- _publish(channel, payload);
- },
-
- /**
- * Reloads the data from browser storage
- */
- reInit: function(){
- _reloadData();
- }
- };
-
- // Initialize jStorage
- _init();
-
-})(); \ No newline at end of file