diff options
author | Ryan Berliner <22206986+RyanBerliner@users.noreply.github.com> | 2021-05-11 08:37:57 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-11 08:37:57 +0300 |
commit | 9c3ab6557ec89ae11cc27da1b4680b3e69381edf (patch) | |
tree | f311d6d71a6729bc29137d25b55f30853f17cde4 /js/src/toast.js | |
parent | c3ad760cd7f7d8c5be80ec067338a9c526679604 (diff) |
Prevent toast autohiding if focusing or hovering (#33221)
Diffstat (limited to 'js/src/toast.js')
-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 c8539b3a96..94a9084ce5 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() { |