Skip to content

Commit

Permalink
Tooltip refactoring (#32523)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
3 people committed Jan 27, 2021
1 parent 3aa3fda commit 5d7b51e
Showing 1 changed file with 74 additions and 84 deletions.
158 changes: 74 additions & 84 deletions js/src/tooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -245,83 +239,85 @@ 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)

const tip = this.getTipElement()
const tipId = getUID(this.constructor.NAME)
if (showEvent.defaultPrevented || !isInTheDom) {
return
}

tip.setAttribute('id', tipId)
this._element.setAttribute('aria-describedby', tipId)
const tip = this.getTipElement()
const tipId = getUID(this.constructor.NAME)

this.setContent()
tip.setAttribute('id', tipId)
this._element.setAttribute('aria-describedby', tipId)

if (this.config.animation) {
tip.classList.add(CLASS_NAME_FADE)
}
this.setContent()

const placement = typeof this.config.placement === 'function' ?
this.config.placement.call(this, tip, this._element) :
this.config.placement
if (this.config.animation) {
tip.classList.add(CLASS_NAME_FADE)
}

const attachment = this._getAttachment(placement)
this._addAttachmentClass(attachment)
const placement = typeof this.config.placement === 'function' ?
this.config.placement.call(this, tip, this._element) :
this.config.placement

const container = this._getContainer()
Data.setData(tip, this.constructor.DATA_KEY, this)
const attachment = this._getAttachment(placement)
this._addAttachmentClass(attachment)

if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
container.appendChild(tip)
}
const container = this._getContainer()
Data.setData(tip, this.constructor.DATA_KEY, this)

EventHandler.trigger(this._element, this.constructor.Event.INSERTED)
if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
container.appendChild(tip)
}

this._popper = Popper.createPopper(this._element, tip, this._getPopperConfig(attachment))
EventHandler.trigger(this._element, this.constructor.Event.INSERTED)

tip.classList.add(CLASS_NAME_SHOW)
this._popper = Popper.createPopper(this._element, tip, this._getPopperConfig(attachment))

const customClass = typeof this.config.customClass === 'function' ? this.config.customClass() : this.config.customClass
if (customClass) {
tip.classList.add(...customClass.split(' '))
}
tip.classList.add(CLASS_NAME_SHOW)

// 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 customClass = typeof this.config.customClass === 'function' ? this.config.customClass() : this.config.customClass
if (customClass) {
tip.classList.add(...customClass.split(' '))
}

const complete = () => {
const prevHoverState = this._hoverState
// 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())
})
}

this._hoverState = null
EventHandler.trigger(this._element, this.constructor.Event.SHOWN)
const complete = () => {
const prevHoverState = this._hoverState

if (prevHoverState === HOVER_STATE_OUT) {
this._leave(null, this)
}
}
this._hoverState = null
EventHandler.trigger(this._element, this.constructor.Event.SHOWN)

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 (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()
}
}

hide() {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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[
Expand Down Expand Up @@ -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[
Expand Down

0 comments on commit 5d7b51e

Please sign in to comment.