Repository URL to install this package:
|
Version:
1.0.1 ▾
|
import { parseRootMargin, shallowCompare } from './utils'
import { ElementWithObserver } from './typings'
import { IntersectionObserverGetPooledOptionsType, ObserverElementMapTypee } from './typings'
export const observerElementsMap: ObserverElementMapTypee = new Map()
export function getPooled(options: IntersectionObserverGetPooledOptionsType = {} as any) {
const root = options.root || null
const rootMargin = parseRootMargin(options.rootMargin)
const threshold = Array.isArray(options.threshold)
? options.threshold
: [options.threshold !== null ? options.threshold : 0]
const observers = observerElementsMap.keys()
let observer
while ((observer = observers.next().value)) {
const unmatched =
root !== observer.root ||
rootMargin !== observer.rootMargin ||
shallowCompare(threshold, observer.thresholds)
if (!unmatched) {
return observer
}
}
return null
}
export function findObserverElement(observer: IntersectionObserver, entry: ElementWithObserver) {
const elements = observerElementsMap.get(observer)
if (elements) {
const values = elements.values()
let element
while ((element = values.next().value)) {
if (element.target === entry.target) {
return element
}
}
}
return null
}
/**
* The Intersection Observer API callback that is called whenever one element,
* called the target, intersects either the device viewport or a specified element.
* Also will get caled whenever the visibility of the target element changes and
* crosses desired amounts of intersection with the root.
* @param {array} changes
* @param {IntersectionObserver} observer
*/
export function callback(changes: any[], observer: IntersectionObserver) {
for (let i = 0; i < changes.length; i++) {
const element = findObserverElement(observer, changes[i])
if (element) {
element.handleChange(changes[i])
}
}
}
export function createObserver(options: any) {
return getPooled(options) || new IntersectionObserver(callback, options)
}
export function observeElement(element: ElementWithObserver) {
if (!observerElementsMap.has(element.observer)) {
observerElementsMap.set(element.observer, new Set())
}
observerElementsMap.get(element.observer)!.add(element)
element.observer.observe(element.target)
}
export function unobserveElement(element: ElementWithObserver) {
if (observerElementsMap.has(element.observer)) {
const targets = observerElementsMap.get(element.observer)!
if (targets.delete(element)) {
if (targets.size > 0) {
element.observer.unobserve(element.target)
} else {
element.observer.disconnect()
observerElementsMap.delete(element.observer)
}
}
}
}