UNPKG

2.91 kBJavaScriptView Raw
1import BaseComponent from 'bootstrap/js/src/base-component.js'
2
3import EventHandler from 'bootstrap/js/src/dom/event-handler'
4import SelectorEngine from 'bootstrap/js/src/dom/selector-engine'
5import Manipulator from 'bootstrap/js/src/dom/manipulator'
6
7import onDocumentScroll from './util/on-document-scroll'
8import { documentScrollTo } from './util/tween'
9
10const NAME = 'backtotop'
11const DATA_KEY = 'bs.backtotop'
12const EVENT_KEY = `.${DATA_KEY}`
13//const DATA_API_KEY = '.data-api'
14
15//const EVENT_SCROLL = `scroll${EVENT_KEY}`
16const EVENT_CLICK = `click${EVENT_KEY}`
17
18const CLASS_NAME_SHOW = 'back-to-top-show'
19
20const SELECTOR_TOGGLE = '[data-bs-toggle="backtotop"]'
21
22const Default = {
23 positionTop: 0,
24 scrollLimit: 100,
25 duration: 800,
26 easing: 'easeInOutSine',
27}
28
29class BackToTop extends BaseComponent {
30 constructor(element, config) {
31 super(element)
32
33 this._config = this._getConfig(config)
34 this._scrollCb = null
35 this._isAnim = false
36 this._prevScrollBehavior = ''
37
38 this._bindEvents()
39 }
40
41 // Getters
42
43 static get NAME() {
44 return NAME
45 }
46
47 // Public
48 show() {
49 if (!this._element.classList.contains(CLASS_NAME_SHOW)) {
50 this._element.classList.add(CLASS_NAME_SHOW)
51 }
52 }
53
54 hide() {
55 if (this._element.classList.contains(CLASS_NAME_SHOW)) {
56 this._element.classList.remove(CLASS_NAME_SHOW)
57 }
58 }
59
60 toggleShow() {
61 if (document.scrollingElement.scrollTop > this._config.scrollLimit) {
62 this.show()
63 } else {
64 this.hide()
65 }
66 }
67
68 scrollToTop() {
69 if (!this._isAnim) {
70 this._isAnim = true
71 documentScrollTo(this._config.positionTop, {
72 duration: this._config.duration,
73 easing: this._config.easing,
74 complete: () => {
75 this._isAnim = false
76 },
77 })
78 }
79 }
80
81 dispose() {
82 if (this._scrollCb) {
83 this._scrollCb.dispose()
84 }
85
86 super.dispose()
87 }
88
89 // Private
90 _getConfig(config) {
91 config = {
92 ...Default,
93 ...Manipulator.getDataAttributes(this._element),
94 ...(typeof config === 'object' ? config : {}),
95 }
96 return config
97 }
98
99 _bindEvents() {
100 this._scrollCb = onDocumentScroll(() => this.toggleShow())
101
102 EventHandler.on(this._element, EVENT_CLICK, (evt) => {
103 evt.preventDefault()
104 this.scrollToTop()
105 })
106 }
107}
108
109/**
110 * ------------------------------------------------------------------------
111 * Data Api implementation
112 * ------------------------------------------------------------------------
113 */
114/*const toggles = SelectorEngine.find(SELECTOR_TOGGLE)
115toggles.forEach((toggle) => {
116 BackToTop.getOrCreateInstance(toggle)
117})*/
118
119const dataApiCb = onDocumentScroll(() => {
120 const toggles = SelectorEngine.find(SELECTOR_TOGGLE)
121 toggles.forEach((toggle) => {
122 const backToTop = BackToTop.getOrCreateInstance(toggle)
123 backToTop.toggleShow()
124 })
125 dataApiCb.dispose()
126})
127
128export default BackToTop