0
0
mirror of https://github.com/twbs/bootstrap.git synced 2025-03-15 15:29:22 +01:00

Tooltip refactoring (#32523)

* tooltip: move common code to a reusable function

* tooltip: return early in `show()`

Co-authored-by: Rohit Sharma <rohit2sharma95@gmail.com>
Co-authored-by: XhmikosR <xhmikosr@gmail.com>
This commit is contained in:
GeoSot 2021-01-27 19:01:24 +02:00 committed by GitHub
parent 3aa3fda730
commit 5d7b51e1d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -191,13 +191,7 @@ class Tooltip extends BaseComponent {
} }
if (event) { if (event) {
const dataKey = this.constructor.DATA_KEY const context = this._initializeOnDelegatedTarget(event)
let context = Data.getData(event.delegateTarget, dataKey)
if (!context) {
context = new this.constructor(event.delegateTarget, this._getDelegateConfig())
Data.setData(event.delegateTarget, dataKey, context)
}
context._activeTrigger.click = !context._activeTrigger.click context._activeTrigger.click = !context._activeTrigger.click
@ -245,82 +239,84 @@ class Tooltip extends BaseComponent {
throw new Error('Please use show on visible elements') throw new Error('Please use show on visible elements')
} }
if (this.isWithContent() && this._isEnabled) { if (!(this.isWithContent() && this._isEnabled)) {
const showEvent = EventHandler.trigger(this._element, this.constructor.Event.SHOW) return
const shadowRoot = findShadowRoot(this._element) }
const isInTheDom = shadowRoot === null ?
this._element.ownerDocument.documentElement.contains(this._element) :
shadowRoot.contains(this._element)
if (showEvent.defaultPrevented || !isInTheDom) { const showEvent = EventHandler.trigger(this._element, this.constructor.Event.SHOW)
return const shadowRoot = findShadowRoot(this._element)
const isInTheDom = shadowRoot === null ?
this._element.ownerDocument.documentElement.contains(this._element) :
shadowRoot.contains(this._element)
if (showEvent.defaultPrevented || !isInTheDom) {
return
}
const tip = this.getTipElement()
const tipId = getUID(this.constructor.NAME)
tip.setAttribute('id', tipId)
this._element.setAttribute('aria-describedby', tipId)
this.setContent()
if (this.config.animation) {
tip.classList.add(CLASS_NAME_FADE)
}
const placement = typeof this.config.placement === 'function' ?
this.config.placement.call(this, tip, this._element) :
this.config.placement
const attachment = this._getAttachment(placement)
this._addAttachmentClass(attachment)
const container = this._getContainer()
Data.setData(tip, this.constructor.DATA_KEY, this)
if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
container.appendChild(tip)
}
EventHandler.trigger(this._element, this.constructor.Event.INSERTED)
this._popper = Popper.createPopper(this._element, tip, this._getPopperConfig(attachment))
tip.classList.add(CLASS_NAME_SHOW)
const customClass = typeof this.config.customClass === 'function' ? this.config.customClass() : this.config.customClass
if (customClass) {
tip.classList.add(...customClass.split(' '))
}
// If this is a touch-enabled device we add extra
// empty mouseover listeners to the body's immediate children;
// only needed because of broken event delegation on iOS
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
if ('ontouchstart' in document.documentElement) {
[].concat(...document.body.children).forEach(element => {
EventHandler.on(element, 'mouseover', noop())
})
}
const complete = () => {
const prevHoverState = this._hoverState
this._hoverState = null
EventHandler.trigger(this._element, this.constructor.Event.SHOWN)
if (prevHoverState === HOVER_STATE_OUT) {
this._leave(null, this)
} }
}
const tip = this.getTipElement() if (this.tip.classList.contains(CLASS_NAME_FADE)) {
const tipId = getUID(this.constructor.NAME) const transitionDuration = getTransitionDurationFromElement(this.tip)
EventHandler.one(this.tip, 'transitionend', complete)
tip.setAttribute('id', tipId) emulateTransitionEnd(this.tip, transitionDuration)
this._element.setAttribute('aria-describedby', tipId) } else {
complete()
this.setContent()
if (this.config.animation) {
tip.classList.add(CLASS_NAME_FADE)
}
const placement = typeof this.config.placement === 'function' ?
this.config.placement.call(this, tip, this._element) :
this.config.placement
const attachment = this._getAttachment(placement)
this._addAttachmentClass(attachment)
const container = this._getContainer()
Data.setData(tip, this.constructor.DATA_KEY, this)
if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
container.appendChild(tip)
}
EventHandler.trigger(this._element, this.constructor.Event.INSERTED)
this._popper = Popper.createPopper(this._element, tip, this._getPopperConfig(attachment))
tip.classList.add(CLASS_NAME_SHOW)
const customClass = typeof this.config.customClass === 'function' ? this.config.customClass() : this.config.customClass
if (customClass) {
tip.classList.add(...customClass.split(' '))
}
// If this is a touch-enabled device we add extra
// empty mouseover listeners to the body's immediate children;
// only needed because of broken event delegation on iOS
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
if ('ontouchstart' in document.documentElement) {
[].concat(...document.body.children).forEach(element => {
EventHandler.on(element, 'mouseover', noop())
})
}
const complete = () => {
const prevHoverState = this._hoverState
this._hoverState = null
EventHandler.trigger(this._element, this.constructor.Event.SHOWN)
if (prevHoverState === HOVER_STATE_OUT) {
this._leave(null, this)
}
}
if (this.tip.classList.contains(CLASS_NAME_FADE)) {
const transitionDuration = getTransitionDurationFromElement(this.tip)
EventHandler.one(this.tip, 'transitionend', complete)
emulateTransitionEnd(this.tip, transitionDuration)
} else {
complete()
}
} }
} }
@ -465,6 +461,18 @@ class Tooltip extends BaseComponent {
// Private // Private
_initializeOnDelegatedTarget(event, context) {
const dataKey = this.constructor.DATA_KEY
context = context || Data.getData(event.delegateTarget, dataKey)
if (!context) {
context = new this.constructor(event.delegateTarget, this._getDelegateConfig())
Data.setData(event.delegateTarget, dataKey, context)
}
return context
}
_getPopperConfig(attachment) { _getPopperConfig(attachment) {
const defaultBsConfig = { const defaultBsConfig = {
placement: attachment, placement: attachment,
@ -582,16 +590,7 @@ class Tooltip extends BaseComponent {
} }
_enter(event, context) { _enter(event, context) {
const dataKey = this.constructor.DATA_KEY context = this._initializeOnDelegatedTarget(event, context)
context = context || Data.getData(event.delegateTarget, dataKey)
if (!context) {
context = new this.constructor(
event.delegateTarget,
this._getDelegateConfig()
)
Data.setData(event.delegateTarget, dataKey, context)
}
if (event) { if (event) {
context._activeTrigger[ context._activeTrigger[
@ -621,16 +620,7 @@ class Tooltip extends BaseComponent {
} }
_leave(event, context) { _leave(event, context) {
const dataKey = this.constructor.DATA_KEY context = this._initializeOnDelegatedTarget(event, context)
context = context || Data.getData(event.delegateTarget, dataKey)
if (!context) {
context = new this.constructor(
event.delegateTarget,
this._getDelegateConfig()
)
Data.setData(event.delegateTarget, dataKey, context)
}
if (event) { if (event) {
context._activeTrigger[ context._activeTrigger[