diff options
author | GeoSot <geo.sotis@gmail.com> | 2021-04-14 23:28:50 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-14 23:28:50 +0300 |
commit | 80085a12f6936bef11aa72631392e3e9b2646f17 (patch) | |
tree | 204f124a4c55bed0c9aeae9cc63a8dde33095ede /js/src/util/backdrop.js | |
parent | 0122e020d60f9556dd9961256633aa06e8ded643 (diff) |
Decouple BackDrop from modal (#32439)
* Create backdrop.js util
* revert breaking changes
remove PromiseTimout usage
revert class name
* one more test | change bundlewatch.config
* add config obj to backdrop helper | tests for rootElement | use transitionend helper
* Minor tweaks — Renaming
Co-authored-by: Rohit Sharma <rohit2sharma95@gmail.com>
Diffstat (limited to 'js/src/util/backdrop.js')
-rw-r--r-- | js/src/util/backdrop.js | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/js/src/util/backdrop.js b/js/src/util/backdrop.js new file mode 100644 index 0000000000..ab14c23fe4 --- /dev/null +++ b/js/src/util/backdrop.js @@ -0,0 +1,123 @@ +/** + * -------------------------------------------------------------------------- + * Bootstrap (v5.0.0-beta3): util/backdrop.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + +import EventHandler from '../dom/event-handler' +import { emulateTransitionEnd, execute, getTransitionDurationFromElement, reflow, typeCheckConfig } from './index' + +const Default = { + isVisible: true, // if false, we use the backdrop helper without adding any element to the dom + isAnimated: false, + rootElement: document.body // give the choice to place backdrop under different elements +} + +const DefaultType = { + isVisible: 'boolean', + isAnimated: 'boolean', + rootElement: 'element' +} +const NAME = 'backdrop' +const CLASS_NAME_BACKDROP = 'modal-backdrop' +const CLASS_NAME_FADE = 'fade' +const CLASS_NAME_SHOW = 'show' + +class Backdrop { + constructor(config) { + this._config = this._getConfig(config) + this._isAppended = false + this._element = null + } + + show(callback) { + if (!this._config.isVisible) { + execute(callback) + return + } + + this._append() + + if (this._config.isAnimated) { + reflow(this._getElement()) + } + + this._getElement().classList.add(CLASS_NAME_SHOW) + + this._emulateAnimation(() => { + execute(callback) + }) + } + + hide(callback) { + if (!this._config.isVisible) { + execute(callback) + return + } + + this._getElement().classList.remove(CLASS_NAME_SHOW) + + this._emulateAnimation(() => { + this.dispose() + execute(callback) + }) + } + + // Private + + _getElement() { + if (!this._element) { + const backdrop = document.createElement('div') + backdrop.className = CLASS_NAME_BACKDROP + if (this._config.isAnimated) { + backdrop.classList.add(CLASS_NAME_FADE) + } + + this._element = backdrop + } + + return this._element + } + + _getConfig(config) { + config = { + ...Default, + ...(typeof config === 'object' ? config : {}) + } + typeCheckConfig(NAME, config, DefaultType) + return config + } + + _append() { + if (this._isAppended) { + return + } + + this._config.rootElement.appendChild(this._getElement()) + + this._isAppended = true + } + + dispose() { + if (!this._isAppended) { + return + } + + this._getElement().parentNode.removeChild(this._element) + this._isAppended = false + } + + _emulateAnimation(callback) { + if (!this._config.isAnimated) { + execute(callback) + return + } + + const backdropTransitionDuration = getTransitionDurationFromElement(this._getElement()) + EventHandler.one(this._getElement(), 'transitionend', () => execute(callback)) + emulateTransitionEnd(this._getElement(), backdropTransitionDuration) + } +} + +export default Backdrop |