UNPKG

32.2 kBJavaScriptView Raw
1/**
2 * SimpleBar.js - v5.2.1
3 * Scrollbars, simpler.
4 * https://grsmto.github.io/simplebar/
5 *
6 * Made by Adrien Denat from a fork by Jonathan Nicol
7 * Under MIT License
8 */
9
10import 'core-js/modules/es.array.filter';
11import 'core-js/modules/es.array.for-each';
12import 'core-js/modules/es.array.iterator';
13import 'core-js/modules/es.object.assign';
14import 'core-js/modules/es.object.to-string';
15import 'core-js/modules/es.parse-int';
16import 'core-js/modules/es.string.iterator';
17import 'core-js/modules/es.weak-map';
18import 'core-js/modules/web.dom-collections.iterator';
19import throttle from 'lodash.throttle';
20import debounce from 'lodash.debounce';
21import memoize from 'lodash.memoize';
22import ResizeObserver from 'resize-observer-polyfill';
23import canUseDOM from 'can-use-dom';
24import 'core-js/modules/es.array.reduce';
25import 'core-js/modules/es.function.name';
26import 'core-js/modules/es.regexp.exec';
27import 'core-js/modules/es.string.match';
28import 'core-js/modules/es.string.replace';
29
30var cachedScrollbarWidth = null;
31var cachedDevicePixelRatio = null;
32
33if (canUseDOM) {
34 window.addEventListener('resize', function () {
35 if (cachedDevicePixelRatio !== window.devicePixelRatio) {
36 cachedDevicePixelRatio = window.devicePixelRatio;
37 cachedScrollbarWidth = null;
38 }
39 });
40}
41
42function scrollbarWidth() {
43 if (cachedScrollbarWidth === null) {
44 if (typeof document === 'undefined') {
45 cachedScrollbarWidth = 0;
46 return cachedScrollbarWidth;
47 }
48
49 var body = document.body;
50 var box = document.createElement('div');
51 box.classList.add('simplebar-hide-scrollbar');
52 body.appendChild(box);
53 var width = box.getBoundingClientRect().right;
54 body.removeChild(box);
55 cachedScrollbarWidth = width;
56 }
57
58 return cachedScrollbarWidth;
59}
60
61function getElementWindow(element) {
62 if (!element || !element.ownerDocument || !element.ownerDocument.defaultView) {
63 return window;
64 }
65
66 return element.ownerDocument.defaultView;
67}
68function getElementDocument(element) {
69 if (!element || !element.ownerDocument) {
70 return document;
71 }
72
73 return element.ownerDocument;
74}
75
76var SimpleBar =
77/*#__PURE__*/
78function () {
79 function SimpleBar(element, options) {
80 var _this = this;
81
82 this.onScroll = function () {
83 var elWindow = getElementWindow(_this.el);
84
85 if (!_this.scrollXTicking) {
86 elWindow.requestAnimationFrame(_this.scrollX);
87 _this.scrollXTicking = true;
88 }
89
90 if (!_this.scrollYTicking) {
91 elWindow.requestAnimationFrame(_this.scrollY);
92 _this.scrollYTicking = true;
93 }
94 };
95
96 this.scrollX = function () {
97 if (_this.axis.x.isOverflowing) {
98 _this.showScrollbar('x');
99
100 _this.positionScrollbar('x');
101 }
102
103 _this.scrollXTicking = false;
104 };
105
106 this.scrollY = function () {
107 if (_this.axis.y.isOverflowing) {
108 _this.showScrollbar('y');
109
110 _this.positionScrollbar('y');
111 }
112
113 _this.scrollYTicking = false;
114 };
115
116 this.onMouseEnter = function () {
117 _this.showScrollbar('x');
118
119 _this.showScrollbar('y');
120 };
121
122 this.onMouseMove = function (e) {
123 _this.mouseX = e.clientX;
124 _this.mouseY = e.clientY;
125
126 if (_this.axis.x.isOverflowing || _this.axis.x.forceVisible) {
127 _this.onMouseMoveForAxis('x');
128 }
129
130 if (_this.axis.y.isOverflowing || _this.axis.y.forceVisible) {
131 _this.onMouseMoveForAxis('y');
132 }
133 };
134
135 this.onMouseLeave = function () {
136 _this.onMouseMove.cancel();
137
138 if (_this.axis.x.isOverflowing || _this.axis.x.forceVisible) {
139 _this.onMouseLeaveForAxis('x');
140 }
141
142 if (_this.axis.y.isOverflowing || _this.axis.y.forceVisible) {
143 _this.onMouseLeaveForAxis('y');
144 }
145
146 _this.mouseX = -1;
147 _this.mouseY = -1;
148 };
149
150 this.onWindowResize = function () {
151 // Recalculate scrollbarWidth in case it's a zoom
152 _this.scrollbarWidth = _this.getScrollbarWidth();
153
154 _this.hideNativeScrollbar();
155 };
156
157 this.hideScrollbars = function () {
158 _this.axis.x.track.rect = _this.axis.x.track.el.getBoundingClientRect();
159 _this.axis.y.track.rect = _this.axis.y.track.el.getBoundingClientRect();
160
161 if (!_this.isWithinBounds(_this.axis.y.track.rect)) {
162 _this.axis.y.scrollbar.el.classList.remove(_this.classNames.visible);
163
164 _this.axis.y.isVisible = false;
165 }
166
167 if (!_this.isWithinBounds(_this.axis.x.track.rect)) {
168 _this.axis.x.scrollbar.el.classList.remove(_this.classNames.visible);
169
170 _this.axis.x.isVisible = false;
171 }
172 };
173
174 this.onPointerEvent = function (e) {
175 var isWithinTrackXBounds, isWithinTrackYBounds;
176 _this.axis.x.track.rect = _this.axis.x.track.el.getBoundingClientRect();
177 _this.axis.y.track.rect = _this.axis.y.track.el.getBoundingClientRect();
178
179 if (_this.axis.x.isOverflowing || _this.axis.x.forceVisible) {
180 isWithinTrackXBounds = _this.isWithinBounds(_this.axis.x.track.rect);
181 }
182
183 if (_this.axis.y.isOverflowing || _this.axis.y.forceVisible) {
184 isWithinTrackYBounds = _this.isWithinBounds(_this.axis.y.track.rect);
185 } // If any pointer event is called on the scrollbar
186
187
188 if (isWithinTrackXBounds || isWithinTrackYBounds) {
189 // Preventing the event's default action stops text being
190 // selectable during the drag.
191 e.preventDefault(); // Prevent event leaking
192
193 e.stopPropagation();
194
195 if (e.type === 'mousedown') {
196 if (isWithinTrackXBounds) {
197 _this.axis.x.scrollbar.rect = _this.axis.x.scrollbar.el.getBoundingClientRect();
198
199 if (_this.isWithinBounds(_this.axis.x.scrollbar.rect)) {
200 _this.onDragStart(e, 'x');
201 } else {
202 _this.onTrackClick(e, 'x');
203 }
204 }
205
206 if (isWithinTrackYBounds) {
207 _this.axis.y.scrollbar.rect = _this.axis.y.scrollbar.el.getBoundingClientRect();
208
209 if (_this.isWithinBounds(_this.axis.y.scrollbar.rect)) {
210 _this.onDragStart(e, 'y');
211 } else {
212 _this.onTrackClick(e, 'y');
213 }
214 }
215 }
216 }
217 };
218
219 this.drag = function (e) {
220 var eventOffset;
221 var track = _this.axis[_this.draggedAxis].track;
222 var trackSize = track.rect[_this.axis[_this.draggedAxis].sizeAttr];
223 var scrollbar = _this.axis[_this.draggedAxis].scrollbar;
224 var contentSize = _this.contentWrapperEl[_this.axis[_this.draggedAxis].scrollSizeAttr];
225 var hostSize = parseInt(_this.elStyles[_this.axis[_this.draggedAxis].sizeAttr], 10);
226 e.preventDefault();
227 e.stopPropagation();
228
229 if (_this.draggedAxis === 'y') {
230 eventOffset = e.pageY;
231 } else {
232 eventOffset = e.pageX;
233 } // Calculate how far the user's mouse is from the top/left of the scrollbar (minus the dragOffset).
234
235
236 var dragPos = eventOffset - track.rect[_this.axis[_this.draggedAxis].offsetAttr] - _this.axis[_this.draggedAxis].dragOffset; // Convert the mouse position into a percentage of the scrollbar height/width.
237
238 var dragPerc = dragPos / (trackSize - scrollbar.size); // Scroll the content by the same percentage.
239
240 var scrollPos = dragPerc * (contentSize - hostSize); // Fix browsers inconsistency on RTL
241
242 if (_this.draggedAxis === 'x') {
243 scrollPos = _this.isRtl && SimpleBar.getRtlHelpers().isRtlScrollbarInverted ? scrollPos - (trackSize + scrollbar.size) : scrollPos;
244 scrollPos = _this.isRtl && SimpleBar.getRtlHelpers().isRtlScrollingInverted ? -scrollPos : scrollPos;
245 }
246
247 _this.contentWrapperEl[_this.axis[_this.draggedAxis].scrollOffsetAttr] = scrollPos;
248 };
249
250 this.onEndDrag = function (e) {
251 var elDocument = getElementDocument(_this.el);
252 var elWindow = getElementWindow(_this.el);
253 e.preventDefault();
254 e.stopPropagation();
255
256 _this.el.classList.remove(_this.classNames.dragging);
257
258 elDocument.removeEventListener('mousemove', _this.drag, true);
259 elDocument.removeEventListener('mouseup', _this.onEndDrag, true);
260 _this.removePreventClickId = elWindow.setTimeout(function () {
261 // Remove these asynchronously so we still suppress click events
262 // generated simultaneously with mouseup.
263 elDocument.removeEventListener('click', _this.preventClick, true);
264 elDocument.removeEventListener('dblclick', _this.preventClick, true);
265 _this.removePreventClickId = null;
266 });
267 };
268
269 this.preventClick = function (e) {
270 e.preventDefault();
271 e.stopPropagation();
272 };
273
274 this.el = element;
275 this.minScrollbarWidth = 20;
276 this.options = Object.assign({}, SimpleBar.defaultOptions, {}, options);
277 this.classNames = Object.assign({}, SimpleBar.defaultOptions.classNames, {}, this.options.classNames);
278 this.axis = {
279 x: {
280 scrollOffsetAttr: 'scrollLeft',
281 sizeAttr: 'width',
282 scrollSizeAttr: 'scrollWidth',
283 offsetSizeAttr: 'offsetWidth',
284 offsetAttr: 'left',
285 overflowAttr: 'overflowX',
286 dragOffset: 0,
287 isOverflowing: true,
288 isVisible: false,
289 forceVisible: false,
290 track: {},
291 scrollbar: {}
292 },
293 y: {
294 scrollOffsetAttr: 'scrollTop',
295 sizeAttr: 'height',
296 scrollSizeAttr: 'scrollHeight',
297 offsetSizeAttr: 'offsetHeight',
298 offsetAttr: 'top',
299 overflowAttr: 'overflowY',
300 dragOffset: 0,
301 isOverflowing: true,
302 isVisible: false,
303 forceVisible: false,
304 track: {},
305 scrollbar: {}
306 }
307 };
308 this.removePreventClickId = null; // Don't re-instantiate over an existing one
309
310 if (SimpleBar.instances.has(this.el)) {
311 return;
312 }
313
314 this.recalculate = throttle(this.recalculate.bind(this), 64);
315 this.onMouseMove = throttle(this.onMouseMove.bind(this), 64);
316 this.hideScrollbars = debounce(this.hideScrollbars.bind(this), this.options.timeout);
317 this.onWindowResize = debounce(this.onWindowResize.bind(this), 64, {
318 leading: true
319 });
320 SimpleBar.getRtlHelpers = memoize(SimpleBar.getRtlHelpers);
321 this.init();
322 }
323 /**
324 * Static properties
325 */
326
327 /**
328 * Helper to fix browsers inconsistency on RTL:
329 * - Firefox inverts the scrollbar initial position
330 * - IE11 inverts both scrollbar position and scrolling offset
331 * Directly inspired by @KingSora's OverlayScrollbars https://github.com/KingSora/OverlayScrollbars/blob/master/js/OverlayScrollbars.js#L1634
332 */
333
334
335 SimpleBar.getRtlHelpers = function getRtlHelpers() {
336 var dummyDiv = document.createElement('div');
337 dummyDiv.innerHTML = '<div class="hs-dummy-scrollbar-size"><div style="height: 200%; width: 200%; margin: 10px 0;"></div></div>';
338 var scrollbarDummyEl = dummyDiv.firstElementChild;
339 document.body.appendChild(scrollbarDummyEl);
340 var dummyContainerChild = scrollbarDummyEl.firstElementChild;
341 scrollbarDummyEl.scrollLeft = 0;
342 var dummyContainerOffset = SimpleBar.getOffset(scrollbarDummyEl);
343 var dummyContainerChildOffset = SimpleBar.getOffset(dummyContainerChild);
344 scrollbarDummyEl.scrollLeft = 999;
345 var dummyContainerScrollOffsetAfterScroll = SimpleBar.getOffset(dummyContainerChild);
346 return {
347 // determines if the scrolling is responding with negative values
348 isRtlScrollingInverted: dummyContainerOffset.left !== dummyContainerChildOffset.left && dummyContainerChildOffset.left - dummyContainerScrollOffsetAfterScroll.left !== 0,
349 // determines if the origin scrollbar position is inverted or not (positioned on left or right)
350 isRtlScrollbarInverted: dummyContainerOffset.left !== dummyContainerChildOffset.left
351 };
352 };
353
354 SimpleBar.getOffset = function getOffset(el) {
355 var rect = el.getBoundingClientRect();
356 var elDocument = getElementDocument(el);
357 var elWindow = getElementWindow(el);
358 return {
359 top: rect.top + (elWindow.pageYOffset || elDocument.documentElement.scrollTop),
360 left: rect.left + (elWindow.pageXOffset || elDocument.documentElement.scrollLeft)
361 };
362 };
363
364 var _proto = SimpleBar.prototype;
365
366 _proto.init = function init() {
367 // Save a reference to the instance, so we know this DOM node has already been instancied
368 SimpleBar.instances.set(this.el, this); // We stop here on server-side
369
370 if (canUseDOM) {
371 this.initDOM();
372 this.scrollbarWidth = this.getScrollbarWidth();
373 this.recalculate();
374 this.initListeners();
375 }
376 };
377
378 _proto.initDOM = function initDOM() {
379 var _this2 = this;
380
381 // make sure this element doesn't have the elements yet
382 if (Array.prototype.filter.call(this.el.children, function (child) {
383 return child.classList.contains(_this2.classNames.wrapper);
384 }).length) {
385 // assume that element has his DOM already initiated
386 this.wrapperEl = this.el.querySelector("." + this.classNames.wrapper);
387 this.contentWrapperEl = this.options.scrollableNode || this.el.querySelector("." + this.classNames.contentWrapper);
388 this.contentEl = this.options.contentNode || this.el.querySelector("." + this.classNames.contentEl);
389 this.offsetEl = this.el.querySelector("." + this.classNames.offset);
390 this.maskEl = this.el.querySelector("." + this.classNames.mask);
391 this.placeholderEl = this.findChild(this.wrapperEl, "." + this.classNames.placeholder);
392 this.heightAutoObserverWrapperEl = this.el.querySelector("." + this.classNames.heightAutoObserverWrapperEl);
393 this.heightAutoObserverEl = this.el.querySelector("." + this.classNames.heightAutoObserverEl);
394 this.axis.x.track.el = this.findChild(this.el, "." + this.classNames.track + "." + this.classNames.horizontal);
395 this.axis.y.track.el = this.findChild(this.el, "." + this.classNames.track + "." + this.classNames.vertical);
396 } else {
397 // Prepare DOM
398 this.wrapperEl = document.createElement('div');
399 this.contentWrapperEl = document.createElement('div');
400 this.offsetEl = document.createElement('div');
401 this.maskEl = document.createElement('div');
402 this.contentEl = document.createElement('div');
403 this.placeholderEl = document.createElement('div');
404 this.heightAutoObserverWrapperEl = document.createElement('div');
405 this.heightAutoObserverEl = document.createElement('div');
406 this.wrapperEl.classList.add(this.classNames.wrapper);
407 this.contentWrapperEl.classList.add(this.classNames.contentWrapper);
408 this.offsetEl.classList.add(this.classNames.offset);
409 this.maskEl.classList.add(this.classNames.mask);
410 this.contentEl.classList.add(this.classNames.contentEl);
411 this.placeholderEl.classList.add(this.classNames.placeholder);
412 this.heightAutoObserverWrapperEl.classList.add(this.classNames.heightAutoObserverWrapperEl);
413 this.heightAutoObserverEl.classList.add(this.classNames.heightAutoObserverEl);
414
415 while (this.el.firstChild) {
416 this.contentEl.appendChild(this.el.firstChild);
417 }
418
419 this.contentWrapperEl.appendChild(this.contentEl);
420 this.offsetEl.appendChild(this.contentWrapperEl);
421 this.maskEl.appendChild(this.offsetEl);
422 this.heightAutoObserverWrapperEl.appendChild(this.heightAutoObserverEl);
423 this.wrapperEl.appendChild(this.heightAutoObserverWrapperEl);
424 this.wrapperEl.appendChild(this.maskEl);
425 this.wrapperEl.appendChild(this.placeholderEl);
426 this.el.appendChild(this.wrapperEl);
427 }
428
429 if (!this.axis.x.track.el || !this.axis.y.track.el) {
430 var track = document.createElement('div');
431 var scrollbar = document.createElement('div');
432 track.classList.add(this.classNames.track);
433 scrollbar.classList.add(this.classNames.scrollbar);
434 track.appendChild(scrollbar);
435 this.axis.x.track.el = track.cloneNode(true);
436 this.axis.x.track.el.classList.add(this.classNames.horizontal);
437 this.axis.y.track.el = track.cloneNode(true);
438 this.axis.y.track.el.classList.add(this.classNames.vertical);
439 this.el.appendChild(this.axis.x.track.el);
440 this.el.appendChild(this.axis.y.track.el);
441 }
442
443 this.axis.x.scrollbar.el = this.axis.x.track.el.querySelector("." + this.classNames.scrollbar);
444 this.axis.y.scrollbar.el = this.axis.y.track.el.querySelector("." + this.classNames.scrollbar);
445
446 if (!this.options.autoHide) {
447 this.axis.x.scrollbar.el.classList.add(this.classNames.visible);
448 this.axis.y.scrollbar.el.classList.add(this.classNames.visible);
449 }
450
451 this.el.setAttribute('data-simplebar', 'init');
452 };
453
454 _proto.initListeners = function initListeners() {
455 var _this3 = this;
456
457 var elWindow = getElementWindow(this.el); // Event listeners
458
459 if (this.options.autoHide) {
460 this.el.addEventListener('mouseenter', this.onMouseEnter);
461 }
462
463 ['mousedown', 'click', 'dblclick'].forEach(function (e) {
464 _this3.el.addEventListener(e, _this3.onPointerEvent, true);
465 });
466 ['touchstart', 'touchend', 'touchmove'].forEach(function (e) {
467 _this3.el.addEventListener(e, _this3.onPointerEvent, {
468 capture: true,
469 passive: true
470 });
471 });
472 this.el.addEventListener('mousemove', this.onMouseMove);
473 this.el.addEventListener('mouseleave', this.onMouseLeave);
474 this.contentWrapperEl.addEventListener('scroll', this.onScroll); // Browser zoom triggers a window resize
475
476 elWindow.addEventListener('resize', this.onWindowResize); // Hack for https://github.com/WICG/ResizeObserver/issues/38
477
478 var resizeObserverStarted = false;
479 var resizeObserver = elWindow.ResizeObserver || ResizeObserver;
480 this.resizeObserver = new resizeObserver(function () {
481 if (!resizeObserverStarted) return;
482
483 _this3.recalculate();
484 });
485 this.resizeObserver.observe(this.el);
486 this.resizeObserver.observe(this.contentEl);
487 elWindow.requestAnimationFrame(function () {
488 resizeObserverStarted = true;
489 }); // This is required to detect horizontal scroll. Vertical scroll only needs the resizeObserver.
490
491 this.mutationObserver = new elWindow.MutationObserver(this.recalculate);
492 this.mutationObserver.observe(this.contentEl, {
493 childList: true,
494 subtree: true,
495 characterData: true
496 });
497 };
498
499 _proto.recalculate = function recalculate() {
500 var elWindow = getElementWindow(this.el);
501 this.elStyles = elWindow.getComputedStyle(this.el);
502 this.isRtl = this.elStyles.direction === 'rtl';
503 var contentElOffsetWidth = this.contentEl.offsetWidth;
504 var isHeightAuto = this.heightAutoObserverEl.offsetHeight <= 1;
505 var isWidthAuto = this.heightAutoObserverEl.offsetWidth <= 1 || contentElOffsetWidth > 0;
506 var contentWrapperElOffsetWidth = this.contentWrapperEl.offsetWidth;
507 var elOverflowX = this.elStyles.overflowX;
508 var elOverflowY = this.elStyles.overflowY;
509 this.contentEl.style.padding = this.elStyles.paddingTop + " " + this.elStyles.paddingRight + " " + this.elStyles.paddingBottom + " " + this.elStyles.paddingLeft;
510 this.wrapperEl.style.margin = "-" + this.elStyles.paddingTop + " -" + this.elStyles.paddingRight + " -" + this.elStyles.paddingBottom + " -" + this.elStyles.paddingLeft;
511 var contentElScrollHeight = this.contentEl.scrollHeight;
512 var contentElScrollWidth = this.contentEl.scrollWidth;
513 this.contentWrapperEl.style.height = isHeightAuto ? 'auto' : '100%'; // Determine placeholder size
514
515 this.placeholderEl.style.width = isWidthAuto ? (contentElOffsetWidth || contentElScrollWidth) + "px" : 'auto';
516 this.placeholderEl.style.height = contentElScrollHeight + "px";
517 var contentWrapperElOffsetHeight = this.contentWrapperEl.offsetHeight;
518 this.axis.x.isOverflowing = contentElOffsetWidth !== 0 && contentElScrollWidth > contentElOffsetWidth;
519 this.axis.y.isOverflowing = contentElScrollHeight > contentWrapperElOffsetHeight; // Set isOverflowing to false if user explicitely set hidden overflow
520
521 this.axis.x.isOverflowing = elOverflowX === 'hidden' ? false : this.axis.x.isOverflowing;
522 this.axis.y.isOverflowing = elOverflowY === 'hidden' ? false : this.axis.y.isOverflowing;
523 this.axis.x.forceVisible = this.options.forceVisible === 'x' || this.options.forceVisible === true;
524 this.axis.y.forceVisible = this.options.forceVisible === 'y' || this.options.forceVisible === true;
525 this.hideNativeScrollbar(); // Set isOverflowing to false if scrollbar is not necessary (content is shorter than offset)
526
527 var offsetForXScrollbar = this.axis.x.isOverflowing ? this.scrollbarWidth : 0;
528 var offsetForYScrollbar = this.axis.y.isOverflowing ? this.scrollbarWidth : 0;
529 this.axis.x.isOverflowing = this.axis.x.isOverflowing && contentElScrollWidth > contentWrapperElOffsetWidth - offsetForYScrollbar;
530 this.axis.y.isOverflowing = this.axis.y.isOverflowing && contentElScrollHeight > contentWrapperElOffsetHeight - offsetForXScrollbar;
531 this.axis.x.scrollbar.size = this.getScrollbarSize('x');
532 this.axis.y.scrollbar.size = this.getScrollbarSize('y');
533 this.axis.x.scrollbar.el.style.width = this.axis.x.scrollbar.size + "px";
534 this.axis.y.scrollbar.el.style.height = this.axis.y.scrollbar.size + "px";
535 this.positionScrollbar('x');
536 this.positionScrollbar('y');
537 this.toggleTrackVisibility('x');
538 this.toggleTrackVisibility('y');
539 }
540 /**
541 * Calculate scrollbar size
542 */
543 ;
544
545 _proto.getScrollbarSize = function getScrollbarSize(axis) {
546 if (axis === void 0) {
547 axis = 'y';
548 }
549
550 if (!this.axis[axis].isOverflowing) {
551 return 0;
552 }
553
554 var contentSize = this.contentEl[this.axis[axis].scrollSizeAttr];
555 var trackSize = this.axis[axis].track.el[this.axis[axis].offsetSizeAttr];
556 var scrollbarSize;
557 var scrollbarRatio = trackSize / contentSize; // Calculate new height/position of drag handle.
558
559 scrollbarSize = Math.max(~~(scrollbarRatio * trackSize), this.options.scrollbarMinSize);
560
561 if (this.options.scrollbarMaxSize) {
562 scrollbarSize = Math.min(scrollbarSize, this.options.scrollbarMaxSize);
563 }
564
565 return scrollbarSize;
566 };
567
568 _proto.positionScrollbar = function positionScrollbar(axis) {
569 if (axis === void 0) {
570 axis = 'y';
571 }
572
573 if (!this.axis[axis].isOverflowing) {
574 return;
575 }
576
577 var contentSize = this.contentWrapperEl[this.axis[axis].scrollSizeAttr];
578 var trackSize = this.axis[axis].track.el[this.axis[axis].offsetSizeAttr];
579 var hostSize = parseInt(this.elStyles[this.axis[axis].sizeAttr], 10);
580 var scrollbar = this.axis[axis].scrollbar;
581 var scrollOffset = this.contentWrapperEl[this.axis[axis].scrollOffsetAttr];
582 scrollOffset = axis === 'x' && this.isRtl && SimpleBar.getRtlHelpers().isRtlScrollingInverted ? -scrollOffset : scrollOffset;
583 var scrollPourcent = scrollOffset / (contentSize - hostSize);
584 var handleOffset = ~~((trackSize - scrollbar.size) * scrollPourcent);
585 handleOffset = axis === 'x' && this.isRtl && SimpleBar.getRtlHelpers().isRtlScrollbarInverted ? handleOffset + (trackSize - scrollbar.size) : handleOffset;
586 scrollbar.el.style.transform = axis === 'x' ? "translate3d(" + handleOffset + "px, 0, 0)" : "translate3d(0, " + handleOffset + "px, 0)";
587 };
588
589 _proto.toggleTrackVisibility = function toggleTrackVisibility(axis) {
590 if (axis === void 0) {
591 axis = 'y';
592 }
593
594 var track = this.axis[axis].track.el;
595 var scrollbar = this.axis[axis].scrollbar.el;
596
597 if (this.axis[axis].isOverflowing || this.axis[axis].forceVisible) {
598 track.style.visibility = 'visible';
599 this.contentWrapperEl.style[this.axis[axis].overflowAttr] = 'scroll';
600 } else {
601 track.style.visibility = 'hidden';
602 this.contentWrapperEl.style[this.axis[axis].overflowAttr] = 'hidden';
603 } // Even if forceVisible is enabled, scrollbar itself should be hidden
604
605
606 if (this.axis[axis].isOverflowing) {
607 scrollbar.style.display = 'block';
608 } else {
609 scrollbar.style.display = 'none';
610 }
611 };
612
613 _proto.hideNativeScrollbar = function hideNativeScrollbar() {
614 this.offsetEl.style[this.isRtl ? 'left' : 'right'] = this.axis.y.isOverflowing || this.axis.y.forceVisible ? "-" + this.scrollbarWidth + "px" : 0;
615 this.offsetEl.style.bottom = this.axis.x.isOverflowing || this.axis.x.forceVisible ? "-" + this.scrollbarWidth + "px" : 0;
616 }
617 /**
618 * On scroll event handling
619 */
620 ;
621
622 _proto.onMouseMoveForAxis = function onMouseMoveForAxis(axis) {
623 if (axis === void 0) {
624 axis = 'y';
625 }
626
627 this.axis[axis].track.rect = this.axis[axis].track.el.getBoundingClientRect();
628 this.axis[axis].scrollbar.rect = this.axis[axis].scrollbar.el.getBoundingClientRect();
629 var isWithinScrollbarBoundsX = this.isWithinBounds(this.axis[axis].scrollbar.rect);
630
631 if (isWithinScrollbarBoundsX) {
632 this.axis[axis].scrollbar.el.classList.add(this.classNames.hover);
633 } else {
634 this.axis[axis].scrollbar.el.classList.remove(this.classNames.hover);
635 }
636
637 if (this.isWithinBounds(this.axis[axis].track.rect)) {
638 this.showScrollbar(axis);
639 this.axis[axis].track.el.classList.add(this.classNames.hover);
640 } else {
641 this.axis[axis].track.el.classList.remove(this.classNames.hover);
642 }
643 };
644
645 _proto.onMouseLeaveForAxis = function onMouseLeaveForAxis(axis) {
646 if (axis === void 0) {
647 axis = 'y';
648 }
649
650 this.axis[axis].track.el.classList.remove(this.classNames.hover);
651 this.axis[axis].scrollbar.el.classList.remove(this.classNames.hover);
652 };
653
654 /**
655 * Show scrollbar
656 */
657 _proto.showScrollbar = function showScrollbar(axis) {
658 if (axis === void 0) {
659 axis = 'y';
660 }
661
662 var scrollbar = this.axis[axis].scrollbar.el;
663
664 if (!this.axis[axis].isVisible) {
665 scrollbar.classList.add(this.classNames.visible);
666 this.axis[axis].isVisible = true;
667 }
668
669 if (this.options.autoHide) {
670 this.hideScrollbars();
671 }
672 }
673 /**
674 * Hide Scrollbar
675 */
676 ;
677
678 /**
679 * on scrollbar handle drag movement starts
680 */
681 _proto.onDragStart = function onDragStart(e, axis) {
682 if (axis === void 0) {
683 axis = 'y';
684 }
685
686 var elDocument = getElementDocument(this.el);
687 var elWindow = getElementWindow(this.el);
688 var scrollbar = this.axis[axis].scrollbar; // Measure how far the user's mouse is from the top of the scrollbar drag handle.
689
690 var eventOffset = axis === 'y' ? e.pageY : e.pageX;
691 this.axis[axis].dragOffset = eventOffset - scrollbar.rect[this.axis[axis].offsetAttr];
692 this.draggedAxis = axis;
693 this.el.classList.add(this.classNames.dragging);
694 elDocument.addEventListener('mousemove', this.drag, true);
695 elDocument.addEventListener('mouseup', this.onEndDrag, true);
696
697 if (this.removePreventClickId === null) {
698 elDocument.addEventListener('click', this.preventClick, true);
699 elDocument.addEventListener('dblclick', this.preventClick, true);
700 } else {
701 elWindow.clearTimeout(this.removePreventClickId);
702 this.removePreventClickId = null;
703 }
704 }
705 /**
706 * Drag scrollbar handle
707 */
708 ;
709
710 _proto.onTrackClick = function onTrackClick(e, axis) {
711 var _this4 = this;
712
713 if (axis === void 0) {
714 axis = 'y';
715 }
716
717 if (!this.options.clickOnTrack) return;
718 var elWindow = getElementWindow(this.el);
719 this.axis[axis].scrollbar.rect = this.axis[axis].scrollbar.el.getBoundingClientRect();
720 var scrollbar = this.axis[axis].scrollbar;
721 var scrollbarOffset = scrollbar.rect[this.axis[axis].offsetAttr];
722 var hostSize = parseInt(this.elStyles[this.axis[axis].sizeAttr], 10);
723 var scrolled = this.contentWrapperEl[this.axis[axis].scrollOffsetAttr];
724 var t = axis === 'y' ? this.mouseY - scrollbarOffset : this.mouseX - scrollbarOffset;
725 var dir = t < 0 ? -1 : 1;
726 var scrollSize = dir === -1 ? scrolled - hostSize : scrolled + hostSize;
727 var speed = 40;
728
729 var scrollTo = function scrollTo() {
730 if (dir === -1) {
731 if (scrolled > scrollSize) {
732 var _this4$contentWrapper;
733
734 scrolled -= speed;
735
736 _this4.contentWrapperEl.scrollTo((_this4$contentWrapper = {}, _this4$contentWrapper[_this4.axis[axis].offsetAttr] = scrolled, _this4$contentWrapper));
737
738 elWindow.requestAnimationFrame(scrollTo);
739 }
740 } else {
741 if (scrolled < scrollSize) {
742 var _this4$contentWrapper2;
743
744 scrolled += speed;
745
746 _this4.contentWrapperEl.scrollTo((_this4$contentWrapper2 = {}, _this4$contentWrapper2[_this4.axis[axis].offsetAttr] = scrolled, _this4$contentWrapper2));
747
748 elWindow.requestAnimationFrame(scrollTo);
749 }
750 }
751 };
752
753 scrollTo();
754 }
755 /**
756 * Getter for content element
757 */
758 ;
759
760 _proto.getContentElement = function getContentElement() {
761 return this.contentEl;
762 }
763 /**
764 * Getter for original scrolling element
765 */
766 ;
767
768 _proto.getScrollElement = function getScrollElement() {
769 return this.contentWrapperEl;
770 };
771
772 _proto.getScrollbarWidth = function getScrollbarWidth() {
773 // Try/catch for FF 56 throwing on undefined computedStyles
774 try {
775 // Detect browsers supporting CSS scrollbar styling and do not calculate
776 if (getComputedStyle(this.contentWrapperEl, '::-webkit-scrollbar').display === 'none' || 'scrollbarWidth' in document.documentElement.style || '-ms-overflow-style' in document.documentElement.style) {
777 return 0;
778 } else {
779 return scrollbarWidth();
780 }
781 } catch (e) {
782 return scrollbarWidth();
783 }
784 };
785
786 _proto.removeListeners = function removeListeners() {
787 var _this5 = this;
788
789 var elWindow = getElementWindow(this.el); // Event listeners
790
791 if (this.options.autoHide) {
792 this.el.removeEventListener('mouseenter', this.onMouseEnter);
793 }
794
795 ['mousedown', 'click', 'dblclick'].forEach(function (e) {
796 _this5.el.removeEventListener(e, _this5.onPointerEvent, true);
797 });
798 ['touchstart', 'touchend', 'touchmove'].forEach(function (e) {
799 _this5.el.removeEventListener(e, _this5.onPointerEvent, {
800 capture: true,
801 passive: true
802 });
803 });
804 this.el.removeEventListener('mousemove', this.onMouseMove);
805 this.el.removeEventListener('mouseleave', this.onMouseLeave);
806 this.contentWrapperEl.removeEventListener('scroll', this.onScroll);
807 elWindow.removeEventListener('resize', this.onWindowResize);
808 this.mutationObserver.disconnect();
809 this.resizeObserver.disconnect(); // Cancel all debounced functions
810
811 this.recalculate.cancel();
812 this.onMouseMove.cancel();
813 this.hideScrollbars.cancel();
814 this.onWindowResize.cancel();
815 }
816 /**
817 * UnMount mutation observer and delete SimpleBar instance from DOM element
818 */
819 ;
820
821 _proto.unMount = function unMount() {
822 this.removeListeners();
823 SimpleBar.instances.delete(this.el);
824 }
825 /**
826 * Check if mouse is within bounds
827 */
828 ;
829
830 _proto.isWithinBounds = function isWithinBounds(bbox) {
831 return this.mouseX >= bbox.left && this.mouseX <= bbox.left + bbox.width && this.mouseY >= bbox.top && this.mouseY <= bbox.top + bbox.height;
832 }
833 /**
834 * Find element children matches query
835 */
836 ;
837
838 _proto.findChild = function findChild(el, query) {
839 var matches = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
840 return Array.prototype.filter.call(el.children, function (child) {
841 return matches.call(child, query);
842 })[0];
843 };
844
845 return SimpleBar;
846}();
847
848SimpleBar.defaultOptions = {
849 autoHide: true,
850 forceVisible: false,
851 clickOnTrack: true,
852 classNames: {
853 contentEl: 'simplebar-content',
854 contentWrapper: 'simplebar-content-wrapper',
855 offset: 'simplebar-offset',
856 mask: 'simplebar-mask',
857 wrapper: 'simplebar-wrapper',
858 placeholder: 'simplebar-placeholder',
859 scrollbar: 'simplebar-scrollbar',
860 track: 'simplebar-track',
861 heightAutoObserverWrapperEl: 'simplebar-height-auto-observer-wrapper',
862 heightAutoObserverEl: 'simplebar-height-auto-observer',
863 visible: 'simplebar-visible',
864 horizontal: 'simplebar-horizontal',
865 vertical: 'simplebar-vertical',
866 hover: 'simplebar-hover',
867 dragging: 'simplebar-dragging'
868 },
869 scrollbarMinSize: 25,
870 scrollbarMaxSize: 0,
871 timeout: 1000
872};
873SimpleBar.instances = new WeakMap();
874
875export default SimpleBar;
876//# sourceMappingURL=simplebar-core.esm.js.map