Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 12 additions & 134 deletions js/src/toast.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import BaseComponent from './base-component.js'
import EventHandler from './dom/event-handler.js'
import { enableDismissTrigger } from './util/component-functions.js'
import { reflow } from './util/index.js'

/**
* Constants
Expand All @@ -18,57 +17,28 @@ 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 DefaultType = {
animation: 'boolean',
autohide: 'boolean',
delay: 'number'
}

const Default = {
animation: true,
autohide: true,
delay: 5000
}
const ANIMATION_NAME_AUTOHIDE = 'toast-autohide'

/**
* Class definition
*/

class Toast extends BaseComponent {
constructor(element, config) {
super(element, config)

this._timeout = null
this._hasMouseInteraction = false
this._hasKeyboardInteraction = false
this._setListeners()
}

// Getters
static get Default() {
return Default
static get NAME() {
return NAME
}

static get DefaultType() {
return DefaultType
}
constructor(element, config) {
super(element, config)

static get NAME() {
return NAME
EventHandler.on(this._element, 'animationend', event => this._onAnimationEnd(event))
}

// Public
Expand All @@ -79,118 +49,26 @@ class Toast extends BaseComponent {
return
}

this._clearTimeout()

if (this._config.animation) {
this._element.classList.add(CLASS_NAME_FADE)
}

const complete = () => {
this._element.classList.remove(CLASS_NAME_SHOWING)
EventHandler.trigger(this._element, EVENT_SHOWN)

this._maybeScheduleHide()
}

this._element.classList.remove(CLASS_NAME_HIDE) // @deprecated
reflow(this._element)
this._element.classList.add(CLASS_NAME_SHOW, CLASS_NAME_SHOWING)

this._queueCallback(complete, this._element, this._config.animation)
this._element.classList.add(CLASS_NAME_SHOW)
EventHandler.trigger(this._element, EVENT_SHOWN)
}

hide() {
if (!this.isShown()) {
return
}

const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE)

if (hideEvent.defaultPrevented) {
return
}

const complete = () => {
this._element.classList.add(CLASS_NAME_HIDE) // @deprecated
this._element.classList.remove(CLASS_NAME_SHOWING, CLASS_NAME_SHOW)
EventHandler.trigger(this._element, EVENT_HIDDEN)
}

this._element.classList.add(CLASS_NAME_SHOWING)
this._queueCallback(complete, this._element, this._config.animation)
}

dispose() {
this._clearTimeout()

if (this.isShown()) {
this._element.classList.remove(CLASS_NAME_SHOW)
}

super.dispose()
}

isShown() {
return this._element.classList.contains(CLASS_NAME_SHOW)
this._element.classList.remove(CLASS_NAME_SHOW)
EventHandler.trigger(this._element, EVENT_HIDDEN)
}

// Private
_maybeScheduleHide() {
if (!this._config.autohide) {
return
}

if (this._hasMouseInteraction || this._hasKeyboardInteraction) {
return
}

this._timeout = setTimeout(() => {
_onAnimationEnd(event) {
if (event.animationName === ANIMATION_NAME_AUTOHIDE) {
this.hide()
}, this._config.delay)
}

_onInteraction(event, isInteracting) {
switch (event.type) {
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._element === nextElement || this._element.contains(nextElement)) {
return
}

this._maybeScheduleHide()
}

_setListeners() {
EventHandler.on(this._element, EVENT_MOUSEOVER, event => this._onInteraction(event, true))
EventHandler.on(this._element, EVENT_MOUSEOUT, event => this._onInteraction(event, false))
EventHandler.on(this._element, EVENT_FOCUSIN, event => this._onInteraction(event, true))
EventHandler.on(this._element, EVENT_FOCUSOUT, event => this._onInteraction(event, false))
}

_clearTimeout() {
clearTimeout(this._timeout)
this._timeout = null
}
}

Expand Down
Loading
Loading