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:
parent
3aa3fda730
commit
5d7b51e1d0
@ -191,13 +191,7 @@ class Tooltip extends BaseComponent {
|
||||
}
|
||||
|
||||
if (event) {
|
||||
const dataKey = this.constructor.DATA_KEY
|
||||
let context = Data.getData(event.delegateTarget, dataKey)
|
||||
|
||||
if (!context) {
|
||||
context = new this.constructor(event.delegateTarget, this._getDelegateConfig())
|
||||
Data.setData(event.delegateTarget, dataKey, context)
|
||||
}
|
||||
const context = this._initializeOnDelegatedTarget(event)
|
||||
|
||||
context._activeTrigger.click = !context._activeTrigger.click
|
||||
|
||||
@ -245,82 +239,84 @@ class Tooltip extends BaseComponent {
|
||||
throw new Error('Please use show on visible elements')
|
||||
}
|
||||
|
||||
if (this.isWithContent() && this._isEnabled) {
|
||||
const showEvent = EventHandler.trigger(this._element, this.constructor.Event.SHOW)
|
||||
const shadowRoot = findShadowRoot(this._element)
|
||||
const isInTheDom = shadowRoot === null ?
|
||||
this._element.ownerDocument.documentElement.contains(this._element) :
|
||||
shadowRoot.contains(this._element)
|
||||
if (!(this.isWithContent() && this._isEnabled)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (showEvent.defaultPrevented || !isInTheDom) {
|
||||
return
|
||||
const showEvent = EventHandler.trigger(this._element, this.constructor.Event.SHOW)
|
||||
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()
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
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
|
||||
|
||||
_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) {
|
||||
const defaultBsConfig = {
|
||||
placement: attachment,
|
||||
@ -582,16 +590,7 @@ class Tooltip extends BaseComponent {
|
||||
}
|
||||
|
||||
_enter(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)
|
||||
}
|
||||
context = this._initializeOnDelegatedTarget(event, context)
|
||||
|
||||
if (event) {
|
||||
context._activeTrigger[
|
||||
@ -621,16 +620,7 @@ class Tooltip extends BaseComponent {
|
||||
}
|
||||
|
||||
_leave(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)
|
||||
}
|
||||
context = this._initializeOnDelegatedTarget(event, context)
|
||||
|
||||
if (event) {
|
||||
context._activeTrigger[
|
||||
|
Loading…
x
Reference in New Issue
Block a user