(function(F){ const tryStorage = function f(obj){ if(!f.key) f.key = 'fossil.access.check'; try{ obj.setItem(f.key, 'f'); const x = obj.getItem(f.key); obj.removeItem(f.key); if(x!=='f') throw new Error(f.key+" failed") return obj; }catch(e){ return undefined; } }; const $storage = tryStorage(window.localStorage) || tryStorage(window.sessionStorage) || tryStorage({ $$$:{}, setItem: function(k,v){this.$$$[k]=v}, getItem: function(k){ return this.$$$.hasOwnProperty(k) ? this.$$$[k] : undefined; }, removeItem: function(k){delete this.$$$[k]}, clear: function(){this.$$$={}} }); const $storageHolder = $storage.hasOwnProperty('$$$') ? $storage.$$$ : $storage; const storageKeyPrefix = ( $storageHolder===$storage ? ( F.config.projectCode || F.config.projectName || F.config.shortProjectName || window.location.pathname )+'::' : ( '' ) ); F.storage = { storageKeyPrefix: storageKeyPrefix, set: (k,v)=>$storage.setItem(storageKeyPrefix+k,v), setJSON: (k,v)=>$storage.setItem(storageKeyPrefix+k,JSON.stringify(v)), get: (k,dflt)=>$storageHolder.hasOwnProperty( storageKeyPrefix+k ) ? $storage.getItem(storageKeyPrefix+k) : dflt, getBool: function(k,dflt){ return 'true'===this.get(k,''+(!!dflt)); }, getJSON: function f(k,dflt){ try { const x = this.get(k,f); return x===f ? dflt : JSON.parse(x); } catch(e){return dflt} }, contains: (k)=>$storageHolder.hasOwnProperty(storageKeyPrefix+k), remove: function(k){ $storage.removeItem(storageKeyPrefix+k); return this; }, clear: function(){ this.keys().forEach((k)=>$storage.removeItem(k)); return this; }, keys: ()=>Object.keys($storageHolder).filter((v)=>(v||'').startsWith(storageKeyPrefix)), isTransient: ()=>$storageHolder!==$storage, storageImplName: function(){ if($storage===window.localStorage) return 'localStorage'; else if($storage===window.sessionStorage) return 'sessionStorage'; else return 'transient'; }, storageHelpDescription: function(){ return { localStorage: "Browser-local persistent storage with an "+ "unspecified long-term lifetime (survives closing the browser, "+ "but maybe not a browser upgrade).", sessionStorage: "Storage local to this browser tab, "+ "lost if this tab is closed.", "transient": "Transient storage local to this invocation of this page." }[this.storageImplName()]; } }; })(window.fossil);