Compare commits

...
Sign in to create a new pull request.

4 commits

Author SHA1 Message Date
XhmikosR
281ef7524f
Merge branch 'main' into tooltip-changes 2021-01-13 22:25:34 +02:00
GeoSot
b53f686fc7 revert focusIn fix, noop() to noop, correct check 2021-01-06 02:01:33 +02:00
XhmikosR
3910ac0c33 Update tooltip.js 2021-01-06 02:01:33 +02:00
GeoSot
e2e0e893b3 initial 2021-01-06 02:01:33 +02:00

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,76 @@ 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(' '))
}
this._enableIosTouchEventsTrick()
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()
}
} }
} }
@ -352,12 +340,7 @@ class Tooltip extends BaseComponent {
tip.classList.remove(CLASS_NAME_SHOW) tip.classList.remove(CLASS_NAME_SHOW)
// If this is a touch-enabled device we remove the extra this._enableIosTouchEventsTrick()
// empty mouseover listeners we added for iOS support
if ('ontouchstart' in document.documentElement) {
[].concat(...document.body.children)
.forEach(element => EventHandler.off(element, 'mouseover', noop))
}
this._activeTrigger[TRIGGER_CLICK] = false this._activeTrigger[TRIGGER_CLICK] = false
this._activeTrigger[TRIGGER_FOCUS] = false this._activeTrigger[TRIGGER_FOCUS] = false
@ -440,7 +423,7 @@ class Tooltip extends BaseComponent {
} }
getTitle() { getTitle() {
let title = this._element.getAttribute('data-bs-original-title') let title = Manipulator.getDataAttribute(this._element, 'original-title')
if (!title) { if (!title) {
title = typeof this.config.title === 'function' ? title = typeof this.config.title === 'function' ?
@ -465,6 +448,30 @@ 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
}
_enableIosTouchEventsTrick() {
// 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)
})
}
}
_getPopperConfig(attachment) { _getPopperConfig(attachment) {
const defaultBsConfig = { const defaultBsConfig = {
placement: attachment, placement: attachment,
@ -546,7 +553,7 @@ class Tooltip extends BaseComponent {
EventHandler.on(this._element, eventIn, this.config.selector, event => this._enter(event)) EventHandler.on(this._element, eventIn, this.config.selector, event => this._enter(event))
EventHandler.on(this._element, eventOut, this.config.selector, event => this._leave(event)) EventHandler.on(this._element, eventOut, this.config.selector, event => this._leave(event))
} }
}) }, this)
this._hideModalHandler = () => { this._hideModalHandler = () => {
if (this._element) { if (this._element) {
@ -569,10 +576,10 @@ class Tooltip extends BaseComponent {
_fixTitle() { _fixTitle() {
const title = this._element.getAttribute('title') const title = this._element.getAttribute('title')
const originalTitleType = typeof this._element.getAttribute('data-bs-original-title') const originalTitleType = typeof Manipulator.getDataAttribute(this._element, 'original-title')
if (title || originalTitleType !== 'string') { if (title || originalTitleType !== 'string') {
this._element.setAttribute('data-bs-original-title', title || '') Manipulator.setDataAttribute(this._element, 'original-title', title || '')
if (title && !this._element.getAttribute('aria-label') && !this._element.textContent) { if (title && !this._element.getAttribute('aria-label') && !this._element.textContent) {
this._element.setAttribute('aria-label', title) this._element.setAttribute('aria-label', title)
} }
@ -582,16 +589,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 +619,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[