Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/twbs/bootstrap.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeoSot <geo.sotis@gmail.com>2022-09-17 18:39:50 +0300
committerGeoSot <geo.sotis@gmail.com>2022-09-17 18:39:50 +0300
commit680b933f68422fac3aa485cc47d160104678dd38 (patch)
tree0bbf5e30e59ce1af98f20f43e9625d5d69d1ad22
parentce6a22159a663e7803b7307a03cf5b002f7ca841 (diff)
-rw-r--r--js/src/base.js34
-rw-r--r--js/src/toa.js186
2 files changed, 184 insertions, 36 deletions
diff --git a/js/src/base.js b/js/src/base.js
index 3e52b98f10..e85dc9be88 100644
--- a/js/src/base.js
+++ b/js/src/base.js
@@ -1,3 +1,35 @@
-class Base extends HTMLElement {}
+import { executeAfterTransition } from './util/index'
+import Manipulator from './dom/manipulator'
+
+class Base extends HTMLElement {
+ constructor(config) {
+ super()
+
+ this._config = this._mergeConfigObj(config, this)
+ }
+
+ _queueCallback(callback, element, isAnimated = true) {
+ executeAfterTransition(callback, element, isAnimated)
+ }
+
+ static get DATA_KEY() {
+ return `bs.${this.NAME}`
+ }
+
+ static get EVENT_KEY() {
+ return `.${this.DATA_KEY}`
+ }
+
+ _mergeConfigObj(config, element) {
+ const jsonConfig = Manipulator.getDataAttribute(element, 'config') // try to parse
+
+ return {
+ ...this.constructor.Default,
+ ...(typeof jsonConfig === 'object' ? jsonConfig : {}),
+ ...Manipulator.getDataAttributes(element),
+ ...(typeof config === 'object' ? config : {})
+ }
+ }
+}
export default Base
diff --git a/js/src/toa.js b/js/src/toa.js
index 85c2b90571..19bbe23b45 100644
--- a/js/src/toa.js
+++ b/js/src/toa.js
@@ -5,71 +5,187 @@
* --------------------------------------------------------------------------
*/
import Base from './base'
+import EventHandler from './dom/event-handler'
+
+const NAME = 'toast'
+const DATA_KEY = 'bs.toast'
+const EVENT_KEY = `.${DATA_KEY}`
+
+const EVENT_MOUSEOVER = `mouseover${EVENT_KEY}`
+const EVENT_MOUSEOUT = `mouseout${EVENT_KEY}`
+const EVENT_FOCUSIN = `focusin${EVENT_KEY}`
+const EVENT_FOCUSOUT = `focusout${EVENT_KEY}`
+const EVENT_HIDE = `hide${EVENT_KEY}`
+const EVENT_HIDDEN = `hidden${EVENT_KEY}`
+const EVENT_SHOW = `show${EVENT_KEY}`
+const EVENT_SHOWN = `shown${EVENT_KEY}`
+
+const CLASS_NAME_FADE = 'fade'
+const CLASS_NAME_HIDE = 'hide' // @deprecated - kept here only for backwards compatibility
+const CLASS_NAME_SHOW = 'show'
+const CLASS_NAME_SHOWING = 'showing'
//
// const TEMPLATE = '<slot></slot>'
+const DefaultType = {
+ animation: 'boolean',
+ autohide: 'boolean',
+ delay: 'number'
+}
+
+const Default = {
+ animation: true,
+ autohide: true,
+ delay: 5000
+}
+
export default class Toa extends Base {
constructor() {
super()
- this.autohide = this.getAttribute('autohide') !== 'false'
- console.log(this.autohide) // eslint-disable-line no-console
- this.classList.add('toast', 'bg-danger', 'p-2')
+ console.log(this._config) // eslint-disable-line no-console
+ this.classList.add('toast', 'p-2')
this.setAttribute('role', 'alert')
- this.ariaLive = 'assertlive'
- this.ariaAtomic = 'true'
+ this.setAttribute('aria-live', 'assertlive')
+ this.setAttribute('aria-atomic', 'true')
+ this._timeout = null
+ this._hasMouseInteraction = false
+ this._hasKeyboardInteraction = false
+ }
+
+ static get Default() {
+ return Default
+ }
+
+ static get DefaultType() {
+ return DefaultType
+ }
+
+ static get NAME() {
+ return NAME
}
show() {
- this.classList.add('show')
- this.style.display = 'block'
- if (this.autohide) {
- setTimeout(() => this.hide(), this.constructor.properties.delay.value)
+ const showEvent = EventHandler.trigger(this, EVENT_SHOW)
+
+ if (showEvent.defaultPrevented) {
+ return
+ }
+
+ this._clearTimeout()
+
+ if (this._config.animation) {
+ this.classList.add(CLASS_NAME_FADE)
+ }
+
+ const complete = () => {
+ this.classList.remove(CLASS_NAME_SHOWING)
+ EventHandler.trigger(this, EVENT_SHOWN)
+
+ this._maybeScheduleHide()
}
+
+ this.classList.remove(CLASS_NAME_HIDE) // @deprecated
+ // reflow(this)
+ this.style.display = 'block'
+ this.classList.add(CLASS_NAME_SHOW, CLASS_NAME_SHOWING)
+
+ this._queueCallback(complete, this, this._config.animation)
}
hide() {
- if (this._hasMouseInteraction) {
- setTimeout(() => this.hide(), this.constructor.properties.delay.value)
+ if (!this.isShown()) {
return
}
- this.style.removeProperty('display')
- this.classList.remove('show')
- }
+ const hideEvent = EventHandler.trigger(this, EVENT_HIDE)
+
+ if (hideEvent.defaultPrevented) {
+ return
+ }
- // Button's properties.
- static get properties() {
- return {
- animation: {
- type: Boolean,
- value: true
- },
- autohide: {
- type: Boolean,
- value: true
- },
- delay: {
- type: Number,
- value: 3000
- }
+ const complete = () => {
+ this.classList.add(CLASS_NAME_HIDE) // @deprecated
+ this.classList.remove(CLASS_NAME_SHOWING, CLASS_NAME_SHOW)
+ EventHandler.trigger(this, EVENT_HIDDEN)
+ this.style.removeProperty('display')
}
+
+ this.classList.add(CLASS_NAME_SHOWING)
+ this._queueCallback(complete, this, this._config.animation)
}
- connectedCallback() {
- this.show()
+ isShown() {
+ return this.classList.contains(CLASS_NAME_SHOW)
+ }
+
+ // Private
+
+ _maybeScheduleHide() {
+ if (!this._config.autohide) {
+ return
+ }
+
+ if (this._hasMouseInteraction || this._hasKeyboardInteraction) {
+ return
+ }
- this.addEventListener('pointerenter', event => this._onInteraction(event, true))
- this.addEventListener('pointerleave', event => this._onInteraction(event, false))
+ this._timeout = setTimeout(() => {
+ this.hide()
+ }, this._config.delay)
}
_onInteraction(event, isInteracting) {
switch (event.type) {
- case 'pointerenter':
- case 'pointerleave':
+ case 'mouseover':
+ case 'mouseout':
this._hasMouseInteraction = isInteracting
break
+ case 'focusin':
+ case 'focusout':
+ this._hasKeyboardInteraction = isInteracting
+ break
default:
break
}
+
+ if (isInteracting) {
+ this._clearTimeout()
+ return
+ }
+
+ const nextElement = event.relatedTarget
+ if (this === nextElement || this.contains(nextElement)) {
+ return
+ }
+
+ this._maybeScheduleHide()
+ }
+
+ _setListeners() {
+ EventHandler.on(this, EVENT_MOUSEOVER, event => this._onInteraction(event, true))
+ EventHandler.on(this, EVENT_MOUSEOUT, event => this._onInteraction(event, false))
+ EventHandler.on(this, EVENT_FOCUSIN, event => this._onInteraction(event, true))
+ EventHandler.on(this, EVENT_FOCUSOUT, event => this._onInteraction(event, false))
}
+
+ _clearTimeout() {
+ clearTimeout(this._timeout)
+ this._timeout = null
+ }
+
+ connectedCallback() {
+ this._setListeners()
+ this.show()
+ }
+
+ //
+ // static get observedAttributes() {
+ // return ['duration'];
+ // }
+ //
+ // attributeChangedCallback(name, oldValue, newValue) {
+ // if (name === 'duration') {
+ // this.duration = newValue;
+ // }
+ // }
}