-
Notifications
You must be signed in to change notification settings - Fork 0
/
instance.ts
134 lines (103 loc) · 3.29 KB
/
instance.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import { getOptions } from './options'
import { createInstance, addIndicators, addObservers } from './element'
import { observe } from './observer'
import { Instance, Elements, Options, directions, PluginOptions } from './types'
import { log, removeHideScrollbarStyle } from './helper'
import { undoMove } from './feature/move-styles'
export const instances = new Map<HTMLElement, Instance>()
const wrappers = new Map<HTMLElement, Instance>()
export const getDOMNodes = (element: Elements) => {
if (typeof element === 'string') {
const elements = document.querySelectorAll(element)
if (elements.length) {
return elements
}
}
if (element instanceof NodeList && element.length) {
return element
}
// Second check to make sure element if attached to DOM.
if (element instanceof HTMLElement && element.isConnected) {
return [element]
}
log('InvalidElement', { element })
return false
}
const hasExistingInstance = (options: Options, element: HTMLElement) => {
let found = false
if (instances.get(element)) {
found = true
}
// Check child in case selector class moved to wrapper.
if (
options.moveStylesToWrapper &&
!found &&
element.childNodes.length > 0 &&
instances.get(element.childNodes[0] as HTMLElement)
) {
found = true
}
if (found) {
log('ExistingInstance', { element })
}
return found
}
export const initialize = (options: Options, element: HTMLElement) => {
if (hasExistingInstance(options, element)) {
return
}
const instance = createInstance(element, options)
addIndicators(instance)
addObservers(instance)
instances.set(element, instance)
wrappers.set(instance.outerWrapper, instance)
observe(instance)
}
export const indicate = (element: Elements, options?: PluginOptions) => {
const elements = getDOMNodes(element)
const instanceOptions = getOptions(options)
if (!elements) {
return
}
if (!IntersectionObserver) {
log('IntersectionObserver')
return
}
elements.forEach(initialize.bind(null, instanceOptions))
}
export const remove = (element: Elements) => {
const elements = getDOMNodes(element)
if (!elements) {
return
}
elements.forEach((currentElement: HTMLElement) => {
const instance = instances.get(currentElement) || wrappers.get(currentElement)
if (!instance) {
log('RemoveNoInstance', { element: currentElement })
return
}
directions.forEach((direction) => {
instance.indicator[direction].remove()
instance.observer[direction].remove()
})
instance.intersectionObserver.disconnect()
removeHideScrollbarStyle(instance.element, instance.innerWrapper)
undoMove(instance.element, instance.outerWrapper, instance)
if (!instance.options.outerWrapper) {
// Remove outer wrapper.
instance.outerWrapper.replaceWith(...Array.from(instance.outerWrapper.childNodes))
}
if (!instance.options.innerWrapper) {
// Remove inner wrapper.
if (instance.table) {
instance.innerWrapper.replaceWith(...Array.from(instance.innerWrapper.childNodes))
} else {
const contents = instance.innerWrapper.innerHTML
instance.innerWrapper.remove()
currentElement.innerHTML = contents
}
}
instances.delete(currentElement)
wrappers.delete(currentElement)
})
}