-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlocal-storage.js
92 lines (82 loc) · 3.1 KB
/
local-storage.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
const string2value = (type, v) =>
{ if( type === 'text')
return v;
if( type === 'json')
try{ return JSON.parse( v );}
catch(err){ return null }
const el = document.createElement('input');
el.setAttribute('type',type);
if( 'number' === type )
{ el.value = v;
return el.valueAsNumber;
}
if( 'date' === type )
{ if(!v) return null;
el.valueAsDate = new Date( v );
return el.value;
}
el.value = v;
return el.value;
};
let originalSetItem,originalRemoveItem,originalClear;
export function localStorage_setItem( key, value )
{ originalSetItem.call(localStorage, key, value);
window.dispatchEvent( new CustomEvent('local-storage',{detail:{key,value}}) );
}
export function localStorage_removeItem( key )
{ originalRemoveItem.call(localStorage, key);
window.dispatchEvent( new CustomEvent('local-storage',{detail:{key}}) );
}
export function localStorage_clear()
{ originalClear.call(localStorage);
window.dispatchEvent( new CustomEvent('local-storage',{detail:{}}) );
}
function ensureTrackLocalStorage()
{ if( originalSetItem )
return;
originalSetItem = localStorage.setItem;
localStorage.setItem = localStorage_setItem;
originalRemoveItem = localStorage.removeItem;
localStorage.removeItem = localStorage_removeItem;
originalClear = localStorage.clear;
localStorage.clear = localStorage_clear;
}
ensureTrackLocalStorage();
export function localStorageSetItem(key, value)
{ localStorage_setItem(key, value);
}
export class LocalStorageElement extends HTMLElement
{
static observedAttributes=
[ 'value' // populated from localStorage, if defined initially, sets the value in storage
, 'slice'
, 'key'
, 'type' // `text|json`, defaults to text, other types are compatible with INPUT field
, 'live' // monitors localStorage change
];
#value;
get value(){ return this.#value ===null ? undefined: this.#value }
set value(o){ return this.#value = o; }
async connectedCallback()
{
const attr = attr => this.getAttribute(attr)
, fromStorage = ()=>
{ this.#value = string2value( attr('type'), localStorage.getItem( attr( 'key' ) ) );
this.dispatchEvent( new Event('change') )
}
this.#value = string2value( attr('type'), localStorage.getItem( attr( 'key' ) ) );
if( this.hasAttribute('value'))
localStorageSetItem( attr( 'key' ), this.#value = attr( 'value' ) )
else
fromStorage()
if( this.hasAttribute('live') )
{ const listener = (e => (e.detail.key === attr( 'key' ) || !e.detail.key ) && fromStorage());
window.addEventListener( 'local-storage', listener );
ensureTrackLocalStorage();
this._destroy = ()=> window.removeEventListener('local-storage', listener );
}
}
disconnectedCallback(){ this._destroy?.(); }
}
window.customElements.define( 'local-storage', LocalStorageElement );
export default LocalStorageElement;