source: trip-planner-front/node_modules/bootstrap/js/src/offcanvas.js@ 6a3a178

Last change on this file since 6a3a178 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 6.6 KB
Line 
1/**
2 * --------------------------------------------------------------------------
3 * Bootstrap (v5.1.3): offcanvas.js
4 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5 * --------------------------------------------------------------------------
6 */
7
8import {
9 defineJQueryPlugin,
10 getElementFromSelector,
11 isDisabled,
12 isVisible,
13 typeCheckConfig
14} from './util/index'
15import ScrollBarHelper from './util/scrollbar'
16import EventHandler from './dom/event-handler'
17import BaseComponent from './base-component'
18import SelectorEngine from './dom/selector-engine'
19import Manipulator from './dom/manipulator'
20import Backdrop from './util/backdrop'
21import FocusTrap from './util/focustrap'
22import { enableDismissTrigger } from './util/component-functions'
23
24/**
25 * ------------------------------------------------------------------------
26 * Constants
27 * ------------------------------------------------------------------------
28 */
29
30const NAME = 'offcanvas'
31const DATA_KEY = 'bs.offcanvas'
32const EVENT_KEY = `.${DATA_KEY}`
33const DATA_API_KEY = '.data-api'
34const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`
35const ESCAPE_KEY = 'Escape'
36
37const Default = {
38 backdrop: true,
39 keyboard: true,
40 scroll: false
41}
42
43const DefaultType = {
44 backdrop: 'boolean',
45 keyboard: 'boolean',
46 scroll: 'boolean'
47}
48
49const CLASS_NAME_SHOW = 'show'
50const CLASS_NAME_BACKDROP = 'offcanvas-backdrop'
51const OPEN_SELECTOR = '.offcanvas.show'
52
53const EVENT_SHOW = `show${EVENT_KEY}`
54const EVENT_SHOWN = `shown${EVENT_KEY}`
55const EVENT_HIDE = `hide${EVENT_KEY}`
56const EVENT_HIDDEN = `hidden${EVENT_KEY}`
57const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
58const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`
59
60const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="offcanvas"]'
61
62/**
63 * ------------------------------------------------------------------------
64 * Class Definition
65 * ------------------------------------------------------------------------
66 */
67
68class Offcanvas extends BaseComponent {
69 constructor(element, config) {
70 super(element)
71
72 this._config = this._getConfig(config)
73 this._isShown = false
74 this._backdrop = this._initializeBackDrop()
75 this._focustrap = this._initializeFocusTrap()
76 this._addEventListeners()
77 }
78
79 // Getters
80
81 static get NAME() {
82 return NAME
83 }
84
85 static get Default() {
86 return Default
87 }
88
89 // Public
90
91 toggle(relatedTarget) {
92 return this._isShown ? this.hide() : this.show(relatedTarget)
93 }
94
95 show(relatedTarget) {
96 if (this._isShown) {
97 return
98 }
99
100 const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, { relatedTarget })
101
102 if (showEvent.defaultPrevented) {
103 return
104 }
105
106 this._isShown = true
107 this._element.style.visibility = 'visible'
108
109 this._backdrop.show()
110
111 if (!this._config.scroll) {
112 new ScrollBarHelper().hide()
113 }
114
115 this._element.removeAttribute('aria-hidden')
116 this._element.setAttribute('aria-modal', true)
117 this._element.setAttribute('role', 'dialog')
118 this._element.classList.add(CLASS_NAME_SHOW)
119
120 const completeCallBack = () => {
121 if (!this._config.scroll) {
122 this._focustrap.activate()
123 }
124
125 EventHandler.trigger(this._element, EVENT_SHOWN, { relatedTarget })
126 }
127
128 this._queueCallback(completeCallBack, this._element, true)
129 }
130
131 hide() {
132 if (!this._isShown) {
133 return
134 }
135
136 const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE)
137
138 if (hideEvent.defaultPrevented) {
139 return
140 }
141
142 this._focustrap.deactivate()
143 this._element.blur()
144 this._isShown = false
145 this._element.classList.remove(CLASS_NAME_SHOW)
146 this._backdrop.hide()
147
148 const completeCallback = () => {
149 this._element.setAttribute('aria-hidden', true)
150 this._element.removeAttribute('aria-modal')
151 this._element.removeAttribute('role')
152 this._element.style.visibility = 'hidden'
153
154 if (!this._config.scroll) {
155 new ScrollBarHelper().reset()
156 }
157
158 EventHandler.trigger(this._element, EVENT_HIDDEN)
159 }
160
161 this._queueCallback(completeCallback, this._element, true)
162 }
163
164 dispose() {
165 this._backdrop.dispose()
166 this._focustrap.deactivate()
167 super.dispose()
168 }
169
170 // Private
171
172 _getConfig(config) {
173 config = {
174 ...Default,
175 ...Manipulator.getDataAttributes(this._element),
176 ...(typeof config === 'object' ? config : {})
177 }
178 typeCheckConfig(NAME, config, DefaultType)
179 return config
180 }
181
182 _initializeBackDrop() {
183 return new Backdrop({
184 className: CLASS_NAME_BACKDROP,
185 isVisible: this._config.backdrop,
186 isAnimated: true,
187 rootElement: this._element.parentNode,
188 clickCallback: () => this.hide()
189 })
190 }
191
192 _initializeFocusTrap() {
193 return new FocusTrap({
194 trapElement: this._element
195 })
196 }
197
198 _addEventListeners() {
199 EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => {
200 if (this._config.keyboard && event.key === ESCAPE_KEY) {
201 this.hide()
202 }
203 })
204 }
205
206 // Static
207
208 static jQueryInterface(config) {
209 return this.each(function () {
210 const data = Offcanvas.getOrCreateInstance(this, config)
211
212 if (typeof config !== 'string') {
213 return
214 }
215
216 if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
217 throw new TypeError(`No method named "${config}"`)
218 }
219
220 data[config](this)
221 })
222 }
223}
224
225/**
226 * ------------------------------------------------------------------------
227 * Data Api implementation
228 * ------------------------------------------------------------------------
229 */
230
231EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
232 const target = getElementFromSelector(this)
233
234 if (['A', 'AREA'].includes(this.tagName)) {
235 event.preventDefault()
236 }
237
238 if (isDisabled(this)) {
239 return
240 }
241
242 EventHandler.one(target, EVENT_HIDDEN, () => {
243 // focus on trigger when it is closed
244 if (isVisible(this)) {
245 this.focus()
246 }
247 })
248
249 // avoid conflict when clicking a toggler of an offcanvas, while another is open
250 const allReadyOpen = SelectorEngine.findOne(OPEN_SELECTOR)
251 if (allReadyOpen && allReadyOpen !== target) {
252 Offcanvas.getInstance(allReadyOpen).hide()
253 }
254
255 const data = Offcanvas.getOrCreateInstance(target)
256 data.toggle(this)
257})
258
259EventHandler.on(window, EVENT_LOAD_DATA_API, () =>
260 SelectorEngine.find(OPEN_SELECTOR).forEach(el => Offcanvas.getOrCreateInstance(el).show())
261)
262
263enableDismissTrigger(Offcanvas)
264/**
265 * ------------------------------------------------------------------------
266 * jQuery
267 * ------------------------------------------------------------------------
268 */
269
270defineJQueryPlugin(Offcanvas)
271
272export default Offcanvas
Note: See TracBrowser for help on using the repository browser.