UNPKG

6.98 kBPlain TextView Raw
1import canUseDOM from 'can-use-dom';
2import SimpleBarCore from 'simplebar-core';
3
4const { getOptions, addClasses } = SimpleBarCore.helpers;
5
6export 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 // // Save a reference to the instance, so we know this DOM node has already been instancied
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 // make sure this element doesn't have the elements yet
43 if (
44 !Array.prototype.filter.call(this.el.children, (child) =>
45 child.classList.contains(this.classNames.wrapper)
46 ).length
47 ) {
48 // Prepare DOM
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 // MutationObserver is IE11+
123 if (typeof MutationObserver !== 'undefined') {
124 // Mutation observer to observe dynamically added elements
125 this.globalObserver = new MutationObserver(SimpleBar.handleMutations);
126
127 this.globalObserver.observe(document, { childList: true, subtree: true });
128 }
129
130 // Taken from jQuery `ready` function
131 // Instantiate elements already present on the page
132 if (
133 document.readyState === 'complete' || // @ts-ignore: IE specific
134 (document.readyState !== 'loading' && !document.documentElement.doScroll)
135 ) {
136 // Handle it asynchronously to allow scripts the opportunity to delay init
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 * HTML API
198 * Called only in a browser env.
199 */
200if (canUseDOM) {
201 SimpleBar.initHtmlApi();
202}