Eduard Kuzmenko
3 years ago
2 changed files with 166 additions and 52 deletions
@ -0,0 +1,105 @@
@@ -0,0 +1,105 @@
|
||||
/* |
||||
* https://github.com/morethanwords/tweb
|
||||
* Copyright (C) 2019-2021 Eduard Kuzmenko |
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/ |
||||
|
||||
export type IntersectionTarget = Element; |
||||
export type IntersectionCallback = (entry: IntersectionObserverEntry) => void; |
||||
|
||||
export default class SuperIntersectionObserver { |
||||
private observing: Map<IntersectionTarget, Set<IntersectionCallback>>; |
||||
private observingQueue: SuperIntersectionObserver['observing']; |
||||
private observer: IntersectionObserver; |
||||
private freezedObservingNew: boolean; |
||||
|
||||
constructor(init?: IntersectionObserverInit) { |
||||
this.observing = new Map(); |
||||
this.observingQueue = new Map(); |
||||
this.freezedObservingNew = false; |
||||
|
||||
this.observer = new IntersectionObserver((entries) => { |
||||
const observing = this.observing; |
||||
for(let i = 0, length = entries.length; i < length; ++i) { |
||||
const entry = entries[i]; |
||||
const callbacks = observing.get(entry.target); |
||||
if(!callbacks) { |
||||
debugger; |
||||
} |
||||
|
||||
for(const callback of callbacks) { |
||||
try { |
||||
callback(entry); |
||||
} catch(err) { |
||||
console.error('intersection process callback error:', err); |
||||
} |
||||
} |
||||
} |
||||
}, init); |
||||
} |
||||
|
||||
public disconnect() { |
||||
this.observer.disconnect(); |
||||
} |
||||
|
||||
public toggleObservingNew(value: boolean) { |
||||
if(this.freezedObservingNew === value) { |
||||
return; |
||||
} |
||||
|
||||
this.freezedObservingNew = value; |
||||
|
||||
const queue = this.observingQueue; |
||||
if(!value && queue.size) { |
||||
for(const [target, callbacks] of queue) { |
||||
for(const callback of callbacks) { |
||||
this.observe(target, callback); |
||||
} |
||||
} |
||||
|
||||
queue.clear(); |
||||
} |
||||
} |
||||
|
||||
public has(target: IntersectionTarget, callback: IntersectionCallback, observing = this.observing) { |
||||
const callbacks = observing.get(target); |
||||
return !!(callbacks && callbacks.has(callback)); |
||||
} |
||||
|
||||
public observe(target: IntersectionTarget, callback: IntersectionCallback) { |
||||
if(this.freezedObservingNew && this.has(target, callback)) { |
||||
return; |
||||
} |
||||
|
||||
const observing = this.freezedObservingNew ? this.observingQueue : this.observing; |
||||
let callbacks = observing.get(target); |
||||
if(callbacks && callbacks.has(callback)) { |
||||
return; |
||||
} |
||||
|
||||
if(!callbacks) { |
||||
callbacks = new Set(); |
||||
observing.set(target, callbacks); |
||||
|
||||
if(observing === this.observing) { |
||||
this.observer.observe(target); |
||||
} |
||||
} |
||||
|
||||
callbacks.add(callback); |
||||
} |
||||
|
||||
public unobserve(target: IntersectionTarget, callback: IntersectionCallback) { |
||||
const observing = this.freezedObservingNew && !this.has(target, callback) ? this.observingQueue : this.observing; |
||||
const callbacks = observing.get(target); |
||||
if(!callbacks) { |
||||
return; |
||||
} |
||||
|
||||
callbacks.delete(callback); |
||||
if(!callbacks.size) { |
||||
observing.delete(target); |
||||
this.observer.unobserve(target); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue