diff options
Diffstat (limited to 'js/src')
| -rw-r--r-- | js/src/toast.js | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/js/src/toast.js b/js/src/toast.js index c8539b3a9..94a9084ce 100644 --- a/js/src/toast.js +++ b/js/src/toast.js @@ -26,6 +26,10 @@ const DATA_KEY = 'bs.toast' const EVENT_KEY = `.${DATA_KEY}` const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_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}` @@ -62,6 +66,8 @@ class Toast extends BaseComponent { this._config = this._getConfig(config) this._timeout = null + this._hasMouseInteraction = false + this._hasKeyboardInteraction = false this._setListeners() } @@ -100,11 +106,7 @@ class Toast extends BaseComponent { EventHandler.trigger(this._element, EVENT_SHOWN) - if (this._config.autohide) { - this._timeout = setTimeout(() => { - this.hide() - }, this._config.delay) - } + this._maybeScheduleHide() } this._element.classList.remove(CLASS_NAME_HIDE) @@ -159,8 +161,53 @@ class Toast extends BaseComponent { return config } + _maybeScheduleHide() { + if (!this._config.autohide) { + return + } + + if (this._hasMouseInteraction || this._hasKeyboardInteraction) { + return + } + + this._timeout = setTimeout(() => { + 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_CLICK_DISMISS, SELECTOR_DATA_DISMISS, () => this.hide()) + 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() { |
