diff options
Diffstat (limited to 'js/dist/offcanvas.js')
-rw-r--r-- | js/dist/offcanvas.js | 509 |
1 files changed, 509 insertions, 0 deletions
diff --git a/js/dist/offcanvas.js b/js/dist/offcanvas.js new file mode 100644 index 0000000000..20bdae46ec --- /dev/null +++ b/js/dist/offcanvas.js @@ -0,0 +1,509 @@ +/*! + * Bootstrap offcanvas.js v5.0.0-beta3 (https://getbootstrap.com/) + * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./dom/selector-engine.js'), require('./dom/manipulator.js'), require('./dom/data.js'), require('./dom/event-handler.js'), require('./base-component.js')) : + typeof define === 'function' && define.amd ? define(['./dom/selector-engine', './dom/manipulator', './dom/data', './dom/event-handler', './base-component'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Offcanvas = factory(global.SelectorEngine, global.Manipulator, global.Data, global.EventHandler, global.Base)); +}(this, (function (SelectorEngine, Manipulator, Data, EventHandler, BaseComponent) { 'use strict'; + + function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } + + var SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine); + var Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator); + var Data__default = /*#__PURE__*/_interopDefaultLegacy(Data); + var EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler); + var BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v5.0.0-beta3): util/index.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + const MILLISECONDS_MULTIPLIER = 1000; + + const toType = obj => { + if (obj === null || obj === undefined) { + return `${obj}`; + } + + return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase(); + }; + + const getSelector = element => { + let selector = element.getAttribute('data-bs-target'); + + if (!selector || selector === '#') { + let hrefAttr = element.getAttribute('href'); // The only valid content that could double as a selector are IDs or classes, + // so everything starting with `#` or `.`. If a "real" URL is used as the selector, + // `document.querySelector` will rightfully complain it is invalid. + // See https://github.com/twbs/bootstrap/issues/32273 + + if (!hrefAttr || !hrefAttr.includes('#') && !hrefAttr.startsWith('.')) { + return null; + } // Just in case some CMS puts out a full URL with the anchor appended + + + if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) { + hrefAttr = '#' + hrefAttr.split('#')[1]; + } + + selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null; + } + + return selector; + }; + + const getSelectorFromElement = element => { + const selector = getSelector(element); + + if (selector) { + return document.querySelector(selector) ? selector : null; + } + + return null; + }; + + const getElementFromSelector = element => { + const selector = getSelector(element); + return selector ? document.querySelector(selector) : null; + }; + + const getTransitionDurationFromElement = element => { + if (!element) { + return 0; + } // Get transition-duration of the element + + + let { + transitionDuration, + transitionDelay + } = window.getComputedStyle(element); + const floatTransitionDuration = Number.parseFloat(transitionDuration); + const floatTransitionDelay = Number.parseFloat(transitionDelay); // Return 0 if element or transition duration is not found + + if (!floatTransitionDuration && !floatTransitionDelay) { + return 0; + } // If multiple durations are defined, take the first + + + transitionDuration = transitionDuration.split(',')[0]; + transitionDelay = transitionDelay.split(',')[0]; + return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER; + }; + + const isElement = obj => (obj[0] || obj).nodeType; + + const typeCheckConfig = (componentName, config, configTypes) => { + Object.keys(configTypes).forEach(property => { + const expectedTypes = configTypes[property]; + const value = config[property]; + const valueType = value && isElement(value) ? 'element' : toType(value); + + if (!new RegExp(expectedTypes).test(valueType)) { + throw new TypeError(`${componentName.toUpperCase()}: ` + `Option "${property}" provided type "${valueType}" ` + `but expected type "${expectedTypes}".`); + } + }); + }; + + const isVisible = element => { + if (!element) { + return false; + } + + if (element.style && element.parentNode && element.parentNode.style) { + const elementStyle = getComputedStyle(element); + const parentNodeStyle = getComputedStyle(element.parentNode); + return elementStyle.display !== 'none' && parentNodeStyle.display !== 'none' && elementStyle.visibility !== 'hidden'; + } + + return false; + }; + + const isDisabled = element => { + if (!element || element.nodeType !== Node.ELEMENT_NODE) { + return true; + } + + if (element.classList.contains('disabled')) { + return true; + } + + if (typeof element.disabled !== 'undefined') { + return element.disabled; + } + + return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'; + }; + + const getjQuery = () => { + const { + jQuery + } = window; + + if (jQuery && !document.body.hasAttribute('data-bs-no-jquery')) { + return jQuery; + } + + return null; + }; + + const onDOMContentLoaded = callback => { + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', callback); + } else { + callback(); + } + }; + + const defineJQueryPlugin = (name, plugin) => { + onDOMContentLoaded(() => { + const $ = getjQuery(); + /* istanbul ignore if */ + + if ($) { + const JQUERY_NO_CONFLICT = $.fn[name]; + $.fn[name] = plugin.jQueryInterface; + $.fn[name].Constructor = plugin; + + $.fn[name].noConflict = () => { + $.fn[name] = JQUERY_NO_CONFLICT; + return plugin.jQueryInterface; + }; + } + }); + }; + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v5.0.0-beta3): util/scrollBar.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed'; + const SELECTOR_STICKY_CONTENT = '.sticky-top'; + + const getWidth = () => { + // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes + const documentWidth = document.documentElement.clientWidth; + return Math.abs(window.innerWidth - documentWidth); + }; + + const hide = (width = getWidth()) => { + document.body.style.overflow = 'hidden'; + + _setElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight', calculatedValue => calculatedValue + width); + + _setElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight', calculatedValue => calculatedValue - width); + + _setElementAttributes('body', 'paddingRight', calculatedValue => calculatedValue + width); + }; + + const _setElementAttributes = (selector, styleProp, callback) => { + const scrollbarWidth = getWidth(); + SelectorEngine__default['default'].find(selector).forEach(element => { + if (element !== document.body && window.innerWidth > element.clientWidth + scrollbarWidth) { + return; + } + + const actualValue = element.style[styleProp]; + const calculatedValue = window.getComputedStyle(element)[styleProp]; + Manipulator__default['default'].setDataAttribute(element, styleProp, actualValue); + element.style[styleProp] = callback(Number.parseFloat(calculatedValue)) + 'px'; + }); + }; + + const reset = () => { + document.body.style.overflow = 'auto'; + + _resetElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight'); + + _resetElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight'); + + _resetElementAttributes('body', 'paddingRight'); + }; + + const _resetElementAttributes = (selector, styleProp) => { + SelectorEngine__default['default'].find(selector).forEach(element => { + const value = Manipulator__default['default'].getDataAttribute(element, styleProp); + + if (typeof value === 'undefined' && element === document.body) { + element.style.removeProperty(styleProp); + } else { + Manipulator__default['default'].removeDataAttribute(element, styleProp); + element.style[styleProp] = value; + } + }); + }; + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v5.0.0-beta3): offcanvas.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + + const NAME = 'offcanvas'; + const DATA_KEY = 'bs.offcanvas'; + const EVENT_KEY = `.${DATA_KEY}`; + const DATA_API_KEY = '.data-api'; + const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`; + const ESCAPE_KEY = 'Escape'; + const Default = { + backdrop: true, + keyboard: true, + scroll: false + }; + const DefaultType = { + backdrop: 'boolean', + keyboard: 'boolean', + scroll: 'boolean' + }; + const CLASS_NAME_BACKDROP_BODY = 'offcanvas-backdrop'; + const CLASS_NAME_SHOW = 'show'; + const CLASS_NAME_TOGGLING = 'offcanvas-toggling'; + const OPEN_SELECTOR = '.offcanvas.show'; + const ACTIVE_SELECTOR = `${OPEN_SELECTOR}, .${CLASS_NAME_TOGGLING}`; + const EVENT_SHOW = `show${EVENT_KEY}`; + const EVENT_SHOWN = `shown${EVENT_KEY}`; + const EVENT_HIDE = `hide${EVENT_KEY}`; + const EVENT_HIDDEN = `hidden${EVENT_KEY}`; + const EVENT_FOCUSIN = `focusin${EVENT_KEY}`; + const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`; + const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}`; + const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="offcanvas"]'; + const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="offcanvas"]'; + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + class Offcanvas extends BaseComponent__default['default'] { + constructor(element, config) { + super(element); + this._config = this._getConfig(config); + this._isShown = false; + + this._addEventListeners(); + } // Getters + + + static get Default() { + return Default; + } + + static get DATA_KEY() { + return DATA_KEY; + } // Public + + + toggle(relatedTarget) { + return this._isShown ? this.hide() : this.show(relatedTarget); + } + + show(relatedTarget) { + if (this._isShown) { + return; + } + + const showEvent = EventHandler__default['default'].trigger(this._element, EVENT_SHOW, { + relatedTarget + }); + + if (showEvent.defaultPrevented) { + return; + } + + this._isShown = true; + this._element.style.visibility = 'visible'; + + if (this._config.backdrop) { + document.body.classList.add(CLASS_NAME_BACKDROP_BODY); + } + + if (!this._config.scroll) { + hide(); + } + + this._element.classList.add(CLASS_NAME_TOGGLING); + + this._element.removeAttribute('aria-hidden'); + + this._element.setAttribute('aria-modal', true); + + this._element.setAttribute('role', 'dialog'); + + this._element.classList.add(CLASS_NAME_SHOW); + + const completeCallBack = () => { + this._element.classList.remove(CLASS_NAME_TOGGLING); + + EventHandler__default['default'].trigger(this._element, EVENT_SHOWN, { + relatedTarget + }); + + this._enforceFocusOnElement(this._element); + }; + + setTimeout(completeCallBack, getTransitionDurationFromElement(this._element)); + } + + hide() { + if (!this._isShown) { + return; + } + + const hideEvent = EventHandler__default['default'].trigger(this._element, EVENT_HIDE); + + if (hideEvent.defaultPrevented) { + return; + } + + this._element.classList.add(CLASS_NAME_TOGGLING); + + EventHandler__default['default'].off(document, EVENT_FOCUSIN); + + this._element.blur(); + + this._isShown = false; + + this._element.classList.remove(CLASS_NAME_SHOW); + + const completeCallback = () => { + this._element.setAttribute('aria-hidden', true); + + this._element.removeAttribute('aria-modal'); + + this._element.removeAttribute('role'); + + this._element.style.visibility = 'hidden'; + + if (this._config.backdrop) { + document.body.classList.remove(CLASS_NAME_BACKDROP_BODY); + } + + if (!this._config.scroll) { + reset(); + } + + EventHandler__default['default'].trigger(this._element, EVENT_HIDDEN); + + this._element.classList.remove(CLASS_NAME_TOGGLING); + }; + + setTimeout(completeCallback, getTransitionDurationFromElement(this._element)); + } // Private + + + _getConfig(config) { + config = { ...Default, + ...Manipulator__default['default'].getDataAttributes(this._element), + ...(typeof config === 'object' ? config : {}) + }; + typeCheckConfig(NAME, config, DefaultType); + return config; + } + + _enforceFocusOnElement(element) { + EventHandler__default['default'].off(document, EVENT_FOCUSIN); // guard against infinite focus loop + + EventHandler__default['default'].on(document, EVENT_FOCUSIN, event => { + if (document !== event.target && element !== event.target && !element.contains(event.target)) { + element.focus(); + } + }); + element.focus(); + } + + _addEventListeners() { + EventHandler__default['default'].on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, () => this.hide()); + EventHandler__default['default'].on(document, 'keydown', event => { + if (this._config.keyboard && event.key === ESCAPE_KEY) { + this.hide(); + } + }); + EventHandler__default['default'].on(document, EVENT_CLICK_DATA_API, event => { + const target = SelectorEngine__default['default'].findOne(getSelectorFromElement(event.target)); + + if (!this._element.contains(event.target) && target !== this._element) { + this.hide(); + } + }); + } // Static + + + static jQueryInterface(config) { + return this.each(function () { + const data = Data__default['default'].get(this, DATA_KEY) || new Offcanvas(this, typeof config === 'object' ? config : {}); + + if (typeof config !== 'string') { + return; + } + + if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { + throw new TypeError(`No method named "${config}"`); + } + + data[config](this); + }); + } + + } + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + + EventHandler__default['default'].on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) { + const target = getElementFromSelector(this); + + if (['A', 'AREA'].includes(this.tagName)) { + event.preventDefault(); + } + + if (isDisabled(this)) { + return; + } + + EventHandler__default['default'].one(target, EVENT_HIDDEN, () => { + // focus on trigger when it is closed + if (isVisible(this)) { + this.focus(); + } + }); // avoid conflict when clicking a toggler of an offcanvas, while another is open + + const allReadyOpen = SelectorEngine__default['default'].findOne(ACTIVE_SELECTOR); + + if (allReadyOpen && allReadyOpen !== target) { + return; + } + + const data = Data__default['default'].get(target, DATA_KEY) || new Offcanvas(target); + data.toggle(this); + }); + EventHandler__default['default'].on(window, EVENT_LOAD_DATA_API, () => { + SelectorEngine__default['default'].find(OPEN_SELECTOR).forEach(el => (Data__default['default'].get(el, DATA_KEY) || new Offcanvas(el)).show()); + }); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + defineJQueryPlugin(NAME, Offcanvas); + + return Offcanvas; + +}))); +//# sourceMappingURL=offcanvas.js.map |