-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmut-obs.ts
105 lines (101 loc) · 4.39 KB
/
mut-obs.ts
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
93
94
95
96
97
98
99
100
101
102
103
104
105
export function upSearch(el: Element, css: string){
if(css === 'parentElement') return el.parentElement;
let upEl = el.previousElementSibling || el.parentElement;
while(upEl && !upEl.matches(css)){
upEl = upEl.previousElementSibling || upEl.parentElement;
}
return upEl;
}
export class MutObs extends HTMLElement{
#observer: MutationObserver | undefined;
connectedCallback(){
this.style.display = 'none';
const g = this.getAttribute.bind(this);
const h = this.hasAttribute.bind(this);
const elToObserve = upSearch(this, g('observe') as string);
if(elToObserve === null) return;
const config : MutationObserverInit = {
attributeFilter: g('attribute-filter') !== null ? JSON.parse(g('attribute-filter') as string) : undefined,
attributes: h('attributes'),
childList: h('child-list'),
subtree: h('subtree'),
attributeOldValue: h('attribute-old-value'),
characterData: h('character-data'),
characterDataOldValue: h('character-data-old-value')
};
const bubbles = h('bubbles');
const composed = h('composed');
const cancelable = h('cancelable');
const unmatchDispatch = g('unmatch-dispatch');
const on = g('on') as string;
const dispatch = g('dispatch') as string;
this.#observer = new MutationObserver((mutRecords: MutationRecord[]) => {
for(const mutRecord of mutRecords){
switch(mutRecord.type){
case 'characterData':
case 'attributes':
const matches = elToObserve.matches(on);
if(matches){
this.dispatchEvent(new CustomEvent(dispatch, {
bubbles,
composed,
cancelable,
detail: {
match: elToObserve
}
}));
}else if(unmatchDispatch !== null){
this.dispatchEvent(new CustomEvent(unmatchDispatch, {
bubbles,
composed,
cancelable,
detail: {
unmatch: elToObserve
}
}));
}
break;
case 'childList':
mutRecord.addedNodes.forEach(node => {
if(node instanceof HTMLElement){
const matches = node.matches(on);
if(matches){
this.dispatchEvent(new CustomEvent(dispatch, {
bubbles,
composed,
cancelable,
detail: {
match: node
}
}));
}
}else if(unmatchDispatch !== null){
this.dispatchEvent(new CustomEvent(unmatchDispatch, {
bubbles,
composed,
cancelable,
detail: {
unmatch: elToObserve
}
}));
}
});
break;
}
//console.log(mutRecord);
//mutRecord.addedNodes
}
});
this.#observer.observe(elToObserve as Element, config);
this.dispatchEvent(new CustomEvent('watching-for-' + g('dispatch'), {
bubbles: h('bubbles'),
composed: h('composed'),
cancelable: h('cancelable')
}));
}
disconnectedCallback(){
this.#observer?.disconnect();
}
}
const is = 'mut-obs';
if(!customElements.get(is)) customElements.define(is, MutObs);