1 | import canUseDOM from 'can-use-dom';
|
2 | import SimpleBarCore from 'simplebar-core';
|
3 |
|
4 | const { getOptions, addClasses } = SimpleBarCore.helpers;
|
5 |
|
6 | export default class SimpleBar extends SimpleBarCore {
|
7 | static globalObserver: MutationObserver;
|
8 |
|
9 | static instances = new WeakMap();
|
10 |
|
11 | constructor(...args: ConstructorParameters<typeof SimpleBarCore>) {
|
12 | super(...args);
|
13 |
|
14 |
|
15 | SimpleBar.instances.set(args[0], this);
|
16 | }
|
17 |
|
18 | static initDOMLoadedElements() {
|
19 | document.removeEventListener(
|
20 | 'DOMContentLoaded',
|
21 | this.initDOMLoadedElements
|
22 | );
|
23 | window.removeEventListener('load', this.initDOMLoadedElements);
|
24 |
|
25 | Array.prototype.forEach.call(
|
26 | document.querySelectorAll('[data-simplebar]'),
|
27 | (el) => {
|
28 | if (
|
29 | el.getAttribute('data-simplebar') !== 'init' &&
|
30 | !SimpleBar.instances.has(el)
|
31 | )
|
32 | new SimpleBar(el, getOptions(el.attributes));
|
33 | }
|
34 | );
|
35 | }
|
36 |
|
37 | static removeObserver() {
|
38 | SimpleBar.globalObserver?.disconnect();
|
39 | }
|
40 |
|
41 | initDOM() {
|
42 |
|
43 | if (
|
44 | !Array.prototype.filter.call(this.el.children, (child) =>
|
45 | child.classList.contains(this.classNames.wrapper)
|
46 | ).length
|
47 | ) {
|
48 |
|
49 | this.wrapperEl = document.createElement('div');
|
50 | this.contentWrapperEl = document.createElement('div');
|
51 | this.offsetEl = document.createElement('div');
|
52 | this.maskEl = document.createElement('div');
|
53 | this.contentEl = document.createElement('div');
|
54 | this.placeholderEl = document.createElement('div');
|
55 | this.heightAutoObserverWrapperEl = document.createElement('div');
|
56 | this.heightAutoObserverEl = document.createElement('div');
|
57 | addClasses(this.wrapperEl, this.classNames.wrapper);
|
58 | addClasses(this.contentWrapperEl, this.classNames.contentWrapper);
|
59 | addClasses(this.offsetEl, this.classNames.offset);
|
60 | addClasses(this.maskEl, this.classNames.mask);
|
61 | addClasses(this.contentEl, this.classNames.contentEl);
|
62 | addClasses(this.placeholderEl, this.classNames.placeholder);
|
63 | addClasses(
|
64 | this.heightAutoObserverWrapperEl,
|
65 | this.classNames.heightAutoObserverWrapperEl
|
66 | );
|
67 | addClasses(
|
68 | this.heightAutoObserverEl,
|
69 | this.classNames.heightAutoObserverEl
|
70 | );
|
71 |
|
72 | while (this.el.firstChild) {
|
73 | this.contentEl.appendChild(this.el.firstChild);
|
74 | }
|
75 |
|
76 | this.contentWrapperEl.appendChild(this.contentEl);
|
77 | this.offsetEl.appendChild(this.contentWrapperEl);
|
78 | this.maskEl.appendChild(this.offsetEl);
|
79 | this.heightAutoObserverWrapperEl.appendChild(this.heightAutoObserverEl);
|
80 | this.wrapperEl.appendChild(this.heightAutoObserverWrapperEl);
|
81 | this.wrapperEl.appendChild(this.maskEl);
|
82 | this.wrapperEl.appendChild(this.placeholderEl);
|
83 | this.el.appendChild(this.wrapperEl);
|
84 |
|
85 | this.contentWrapperEl?.setAttribute('tabindex', '0');
|
86 | this.contentWrapperEl?.setAttribute('role', 'region');
|
87 | this.contentWrapperEl?.setAttribute('aria-label', this.options.ariaLabel);
|
88 | }
|
89 |
|
90 | if (!this.axis.x.track.el || !this.axis.y.track.el) {
|
91 | const track = document.createElement('div');
|
92 | const scrollbar = document.createElement('div');
|
93 |
|
94 | addClasses(track, this.classNames.track);
|
95 | addClasses(scrollbar, this.classNames.scrollbar);
|
96 |
|
97 | track.appendChild(scrollbar);
|
98 |
|
99 | this.axis.x.track.el = track.cloneNode(true) as HTMLElement;
|
100 | addClasses(this.axis.x.track.el, this.classNames.horizontal);
|
101 |
|
102 | this.axis.y.track.el = track.cloneNode(true) as HTMLElement;
|
103 | addClasses(this.axis.y.track.el, this.classNames.vertical);
|
104 |
|
105 | this.el.appendChild(this.axis.x.track.el);
|
106 | this.el.appendChild(this.axis.y.track.el);
|
107 | }
|
108 |
|
109 | SimpleBarCore.prototype.initDOM.call(this);
|
110 |
|
111 | this.el.setAttribute('data-simplebar', 'init');
|
112 | }
|
113 |
|
114 | unMount() {
|
115 | SimpleBarCore.prototype.unMount.call(this);
|
116 | SimpleBar.instances.delete(this.el);
|
117 | }
|
118 |
|
119 | static initHtmlApi() {
|
120 | this.initDOMLoadedElements = this.initDOMLoadedElements.bind(this);
|
121 |
|
122 |
|
123 | if (typeof MutationObserver !== 'undefined') {
|
124 |
|
125 | this.globalObserver = new MutationObserver(SimpleBar.handleMutations);
|
126 |
|
127 | this.globalObserver.observe(document, { childList: true, subtree: true });
|
128 | }
|
129 |
|
130 |
|
131 |
|
132 | if (
|
133 | document.readyState === 'complete' ||
|
134 | (document.readyState !== 'loading' && !document.documentElement.doScroll)
|
135 | ) {
|
136 |
|
137 | window.setTimeout(this.initDOMLoadedElements);
|
138 | } else {
|
139 | document.addEventListener('DOMContentLoaded', this.initDOMLoadedElements);
|
140 | window.addEventListener('load', this.initDOMLoadedElements);
|
141 | }
|
142 | }
|
143 |
|
144 | static handleMutations(mutations: MutationRecord[]) {
|
145 | mutations.forEach((mutation) => {
|
146 | mutation.addedNodes.forEach((addedNode) => {
|
147 | if (addedNode.nodeType === 1) {
|
148 | if ((addedNode as Element).hasAttribute('data-simplebar')) {
|
149 | !SimpleBar.instances.has(addedNode) &&
|
150 | document.documentElement.contains(addedNode) &&
|
151 | new SimpleBar(
|
152 | addedNode as HTMLElement,
|
153 | getOptions((addedNode as Element).attributes)
|
154 | );
|
155 | } else {
|
156 | (addedNode as Element)
|
157 | .querySelectorAll('[data-simplebar]')
|
158 | .forEach((el) => {
|
159 | if (
|
160 | el.getAttribute('data-simplebar') !== 'init' &&
|
161 | !SimpleBar.instances.has(el) &&
|
162 | document.documentElement.contains(el)
|
163 | )
|
164 | new SimpleBar(el as HTMLElement, getOptions(el.attributes));
|
165 | });
|
166 | }
|
167 | }
|
168 | });
|
169 |
|
170 | mutation.removedNodes.forEach((removedNode) => {
|
171 | if (removedNode.nodeType === 1) {
|
172 | if (
|
173 | (removedNode as Element).getAttribute('data-simplebar') === 'init'
|
174 | ) {
|
175 | SimpleBar.instances.has(removedNode) &&
|
176 | !document.documentElement.contains(removedNode) &&
|
177 | SimpleBar.instances.get(removedNode).unMount();
|
178 | } else {
|
179 | Array.prototype.forEach.call(
|
180 | (removedNode as Element).querySelectorAll(
|
181 | '[data-simplebar="init"]'
|
182 | ),
|
183 | (el) => {
|
184 | SimpleBar.instances.has(el) &&
|
185 | !document.documentElement.contains(el) &&
|
186 | SimpleBar.instances.get(el).unMount();
|
187 | }
|
188 | );
|
189 | }
|
190 | }
|
191 | });
|
192 | });
|
193 | }
|
194 | }
|
195 |
|
196 |
|
197 |
|
198 |
|
199 |
|
200 | if (canUseDOM) {
|
201 | SimpleBar.initHtmlApi();
|
202 | }
|