PageSourceSearch

https://bcnsostenible.cat/gl_web/js/plugins/simpleStorage.js

js bcnsostenible.cat collected 2026-10-02 07:43:42 UTC 10,720 bytes, 387 lines download raw bytes

1/* jshint browser: true */
2/* global define: false */
3
4// AMD shim
5(function(root, factory) {
6
7    "use strict";
8
9    if (typeof define === 'function' && define.amd) {
10        define(factory);
11    } else {
12        root.simpleStorage = factory();
13    }
14
15}(this, function() {
16
17    "use strict";
18
19    var
20        VERSION = "0.1.2",
21
22        /* This is the object, that holds the cached values */
23        _storage = false,
24
25        /* How much space does the storage take */
26        _storage_size = 0,
27
28        _storage_available = false,
29
30        _ttl_timeout = null;
31
32    // This method might throw as it touches localStorage and doing so
33    // can be prohibited in some environments
34    function _init(){
35
36        // If localStorage does not exist, the following throws
37        // This is intentional
38        window.localStorage.setItem("__simpleStorageInitTest", "tmpval");
39        window.localStorage.removeItem("__simpleStorageInitTest");
40
41        // Load data from storage
42        _load_storage();
43
44        // remove dead keys
45        _handleTTL();
46
47        // start listening for changes
48        _setupUpdateObserver();
49
50        // handle cached navigation
51        if("addEventListener" in window){
52            window.addEventListener("pageshow", function(event){
53                if(event.persisted){
54                    _reloadData();
55                }
56            }, false);
57        }
58
59        _storage_available = true;
60    }
61
62    /**
63     * Sets up a storage change observer
64     */
65    function _setupUpdateObserver(){
66        if("addEventListener" in window){
67            window.addEventListener("storage", _reloadData, false);
68        }else{
69            document.attachEvent("onstorage", _reloadData);
70        }
71    }
72
73    /**
74     * Reload data from storage when needed
75     */
76    function _reloadData(){
77        try{
78            _load_storage();
79        }catch(E){
80            _storage_available = false;
81            return;
82        }
83        _handleTTL();
84    }
85
86    function _load_storage(){
87        var source = localStorage.simpleStorage;
88
89        try{
90            _storage = JSON.parse(source);
91        }catch(E){
92            _storage = {};
93        }
94
95        _storage_size = localStorage.simpleStorage ? String(localStorage.simpleStorage).length : 0;
96    }
97
98    function _save(){
99        try{
100            localStorage.simpleStorage = JSON.stringify(_storage);
101            _storage_size = localStorage.simpleStorage ? String(localStorage.simpleStorage).length : 0;
102        }catch(E){
103            return E;
104        }
105        return true;
106    }
107
108    function _handleTTL(){
109        var curtime, i, len, expire, keys, nextExpire = Infinity, expiredKeysCount = 0;
110
111        clearTimeout(_ttl_timeout);
112
113        if(!_storage || !_storage.__simpleStorage_meta || !_storage.__simpleStorage_meta.TTL){
114            return;
115        }
116
117        curtime = +new Date();
118        keys = _storage.__simpleStorage_meta.TTL.keys || [];
119        expire = _storage.__simpleStorage_meta.TTL.expire || {};
120
121        for(i = 0, len = keys.length; i<len; i++){
122            if(expire[keys[i]] <= curtime){
123                expiredKeysCount++;
124                delete _storage[keys[i]];
125                delete expire[keys[i]];
126            }else{
127                if(expire[keys[i]] < nextExpire){
128                    nextExpire = expire[keys[i]];
129                }
130                break;
131            }
132        }
133
134        // set next check
135        if(nextExpire != Infinity){
136            _ttl_timeout = setTimeout(_handleTTL, Math.min(nextExpire - curtime, 0x7FFFFFFF));
137        }
138
139        // remove expired from TTL list and save changes
140        if(expiredKeysCount){
141            keys.splice(0, expiredKeysCount);
142
143            _cleanMetaObject();
144            _save();
145        }
146    }
147
148    function _setTTL(key, ttl){
149        var curtime = +new Date(), i, len, added = false;
150
151        ttl = Number(ttl) || 0;
152
153        // Set TTL value for the key
154        if(ttl !== 0){
155            // If key exists, set TTL
156            if(_storage.hasOwnProperty(key)){
157
158                if(!_storage.__simpleStorage_meta){
159                    _storage.__simpleStorage_meta = {};
160                }
161
162                if(!_storage.__simpleStorage_meta.TTL){
163                    _storage.__simpleStorage_meta.TTL = {expire: {}, keys:[]};
164                }
165
166                _storage.__simpleStorage_meta.TTL.expire[key] = curtime + ttl;
167
168                // remove from keys array
169                if(_storage.__simpleStorage_meta.TTL.expire.hasOwnProperty(key)){
170                    for(i = 0, len = _storage.__simpleStorage_meta.TTL.keys.length; i<len; i++){
171                        if(_storage.__simpleStorage_meta.TTL.keys[i] == key){
172                            _storage.__simpleStorage_meta.TTL.keys.splice(i);
173                        }
174                    }
175                }
176
177                // add to keys array, sorted by ttl
178                for(i = 0, len = _storage.__simpleStorage_meta.TTL.keys.length; i<len; i++){
179                    if(_storage.__simpleStorage_meta.TTL.expire[_storage.__simpleStorage_meta.TTL.keys[i]] > curtime + ttl){
180                        _storage.__simpleStorage_meta.TTL.keys.splice(i, 0, key);
181                    }
182                }
183
184                if(!added){
185                    _storage.__simpleStorage_meta.TTL.keys.push(key);
186                }
187            }else{
188                return false;
189            }
190        }else{
191            // Remove TTL if set
192            if(_storage && _storage.__simpleStorage_meta && _storage.__simpleStorage_meta.TTL){
193
194                if(_storage.__simpleStorage_meta.TTL.expire.hasOwnProperty(key)){
195                    delete _storage.__simpleStorage_meta.TTL.expire[key];
196                    for(i = 0, len = _storage.__simpleStorage_meta.TTL.keys.length; i<len; i++){
197                        if(_storage.__simpleStorage_meta.TTL.keys[i] == key){
198                            _storage.__simpleStorage_meta.TTL.keys.splice(i, 1);
199                            break;
200                        }
201                    }
202                }
203
204                _cleanMetaObject();
205            }
206        }
207
208        // schedule next TTL check
209        clearTimeout(_ttl_timeout);
210        if(_storage && _storage.__simpleStorage_meta && _storage.__simpleStorage_meta.TTL && _storage.__simpleStorage_meta.TTL.keys.length){
211            _ttl_timeout = setTimeout(_handleTTL, Math.min(Math.max(_storage.__simpleStorage_meta.TTL.expire[_storage.__simpleStorage_meta.TTL.keys[0]] - curtime, 0), 0x7FFFFFFF));
212        }
213
214        return true;
215    }
216
217    function _cleanMetaObject(){
218        var updated = false, hasProperties = false, i;
219
220        if(!_storage || !_storage.__simpleStorage_meta){
221            return updated;
222        }
223
224        // If nothing to TTL, remove the object
225        if(_storage.__simpleStorage_meta.TTL && !_storage.__simpleStorage_meta.TTL.keys.length){
226            delete _storage.__simpleStorage_meta.TTL;
227            updated = true;
228        }
229
230        // If meta object is empty, remove it
231        for(i in _storage.__simpleStorage_meta){
232            if(_storage.__simpleStorage_meta.hasOwnProperty(i)){
233                hasProperties = true;
234                break;
235            }
236        }
237
238        if(!hasProperties){
239            delete _storage.__simpleStorage_meta;
240            updated = true;
241        }
242
243        return updated;
244    }
245
246    ////////////////////////// PUBLIC INTERFACE /////////////////////////
247
248    try{
249        _init();
250    }catch(E){}
251
252    return {
253
254        version: VERSION,
255
256        canUse: function(){
257            return !!_storage_available;
258        },
259
260        set: function(key, value, options){
261            if(key == "__simpleStorage_meta"){
262                return false;
263            }
264
265            if(!_storage){
266                return false;
267            }
268
269            // undefined values are deleted automatically
270            if(typeof value == "undefined"){
271                return this.deleteKey(key);
272            }
273
274            options = options || {};
275
276            // Check if the value is JSON compatible (and remove reference to existing objects/arrays)
277            try{
278                value = JSON.parse(JSON.stringify(value));
279            }catch(E){
280                return E;
281            }
282
283            _storage[key] = value;
284
285            _setTTL(key, options.TTL || 0);
286
287            return _save();
288        },
289
290        get: function(key){
291            if(!_storage){
292                return false;
293            }
294
295            if(_storage.hasOwnProperty(key) && key != "__simpleStorage_meta"){
296                // TTL value for an existing key is either a positive number or an Infinity
297                if(this.getTTL(key)){
298                    return _storage[key];
299                }
300            }
301        },
302
303        deleteKey: function(key){
304
305            if(!_storage){
306                return false;
307            }
308
309            if(key in _storage){
310                delete _storage[key];
311
312                _setTTL(key, 0);
313
314                return _save();
315            }
316
317            return false;
318        },
319
320        setTTL: function(key, ttl){
321            if(!_storage){
322                return false;
323            }
324
325            _setTTL(key, ttl);
326
327            return _save();
328        },
329
330        getTTL: function(key){
331            var ttl;
332
333            if(!_storage){
334                return false;
335            }
336
337            if(_storage.hasOwnProperty(key)){
338                if(_storage.__simpleStorage_meta &&
339                    _storage.__simpleStorage_meta.TTL &&
340                    _storage.__simpleStorage_meta.TTL.expire &&
341                    _storage.__simpleStorage_meta.TTL.expire.hasOwnProperty(key)){
342
343                    ttl = Math.max(_storage.__simpleStorage_meta.TTL.expire[key] - (+new Date()) || 0, 0);
344
345                    return ttl || false;
346                }else{
347                    return Infinity;
348                }
349            }
350
351            return false;
352        },
353
354        flush: function(){
355            if(!_storage){
356                return false;
357            }
358
359            _storage = {};
360            try{
361                localStorage.removeItem("simpleStorage");
362                return true;
363            }catch(E){
364                return E;
365            }
366        },
367
368        index: function(){
369            if(!_storage){
370                return false;
371            }
372
373            var index = [], i;
374            for(i in _storage){
375                if(_storage.hasOwnProperty(i) && i != "__simpleStorage_meta"){
376                    index.push(i);
377                }
378            }
379            return index;
380        },
381
382        storageSize: function(){
383            return _storage_size;
384        }
385    };
386
387}));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.