diff options
| author | Pierre-Denis Vanduynslager <[email protected]> | 2016-12-28 19:57:38 -0500 |
|---|---|---|
| committer | Pierre-Denis Vanduynslager <[email protected]> | 2016-12-28 19:57:38 -0500 |
| commit | 425d156df27fa6c18e979aa000bfe5a346ee3450 (patch) | |
| tree | 4157dfcbdf8334e9d9fb2bb239f4ae78706bbc71 /js/src/tooltip.js | |
| parent | ab2fc63d08b8c53d6f29bcfd73b7f2d5ceaacacd (diff) | |
| parent | e1e621be046a4541a2fd36e445015ee44de3c67e (diff) | |
| download | bootstrap-425d156df27fa6c18e979aa000bfe5a346ee3450.tar.xz bootstrap-425d156df27fa6c18e979aa000bfe5a346ee3450.zip | |
Merge branch 'twbs/v4-dev' into dropdown-keyboard
Diffstat (limited to 'js/src/tooltip.js')
| -rw-r--r-- | js/src/tooltip.js | 159 |
1 files changed, 91 insertions, 68 deletions
diff --git a/js/src/tooltip.js b/js/src/tooltip.js index 77803dc40..0c1d381b9 100644 --- a/js/src/tooltip.js +++ b/js/src/tooltip.js @@ -5,7 +5,7 @@ import Util from './util' /** * -------------------------------------------------------------------------- - * Bootstrap (v4.0.0-alpha.2): tooltip.js + * Bootstrap (v4.0.0-alpha.5): tooltip.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ @@ -14,10 +14,10 @@ const Tooltip = (($) => { /** * Check for Tether dependency - * Tether - http://github.hubspot.com/tether/ + * Tether - http://tether.io/ */ - if (window.Tether === undefined) { - throw new Error('Bootstrap tooltips require Tether (http://github.hubspot.com/tether/)') + if (typeof Tether === 'undefined') { + throw new Error('Bootstrap tooltips require Tether (http://tether.io/)') } @@ -28,7 +28,7 @@ const Tooltip = (($) => { */ const NAME = 'tooltip' - const VERSION = '4.0.0-alpha.2' + const VERSION = '4.0.0-alpha.5' const DATA_KEY = 'bs.tooltip' const EVENT_KEY = `.${DATA_KEY}` const JQUERY_NO_CONFLICT = $.fn[NAME] @@ -38,7 +38,6 @@ const Tooltip = (($) => { const Default = { animation : true, template : '<div class="tooltip" role="tooltip">' - + '<div class="tooltip-arrow"></div>' + '<div class="tooltip-inner"></div></div>', trigger : 'hover focus', title : '', @@ -47,7 +46,8 @@ const Tooltip = (($) => { selector : false, placement : 'top', offset : '0 0', - constraints : [] + constraints : [], + container : false } const DefaultType = { @@ -60,7 +60,8 @@ const Tooltip = (($) => { selector : '(string|boolean)', placement : '(string|function)', offset : 'string', - constraints : 'array' + constraints : 'array', + container : '(string|element|boolean)' } const AttachmentMap = { @@ -71,8 +72,8 @@ const Tooltip = (($) => { } const HoverState = { - IN : 'in', - OUT : 'out' + SHOW : 'show', + OUT : 'out' } const Event = { @@ -90,7 +91,7 @@ const Tooltip = (($) => { const ClassName = { FADE : 'fade', - IN : 'in' + SHOW : 'show' } const Selector = { @@ -122,11 +123,12 @@ const Tooltip = (($) => { constructor(element, config) { // private - this._isEnabled = true - this._timeout = 0 - this._hoverState = '' - this._activeTrigger = {} - this._tether = null + this._isEnabled = true + this._timeout = 0 + this._hoverState = '' + this._activeTrigger = {} + this._isTransitioning = false + this._tether = null // protected this.element = element @@ -185,7 +187,7 @@ const Tooltip = (($) => { toggle(event) { if (event) { - let dataKey = this.constructor.DATA_KEY + const dataKey = this.constructor.DATA_KEY let context = $(event.currentTarget).data(dataKey) if (!context) { @@ -206,7 +208,7 @@ const Tooltip = (($) => { } else { - if ($(this.getTipElement()).hasClass(ClassName.IN)) { + if ($(this.getTipElement()).hasClass(ClassName.SHOW)) { this._leave(null, this) return } @@ -223,16 +225,17 @@ const Tooltip = (($) => { $.removeData(this.element, this.constructor.DATA_KEY) $(this.element).off(this.constructor.EVENT_KEY) + $(this.element).closest('.modal').off('hide.bs.modal') if (this.tip) { $(this.tip).remove() } - this._isEnabled = null - this._timeout = null - this._hoverState = null - this._activeTrigger = null - this._tether = null + this._isEnabled = null + this._timeout = null + this._hoverState = null + this._activeTrigger = null + this._tether = null this.element = null this.config = null @@ -240,12 +243,18 @@ const Tooltip = (($) => { } show() { - let showEvent = $.Event(this.constructor.Event.SHOW) + if ($(this.element).css('display') === 'none') { + throw new Error('Please use show on visible elements') + } + const showEvent = $.Event(this.constructor.Event.SHOW) if (this.isWithContent() && this._isEnabled) { + if (this._isTransitioning) { + throw new Error('Tooltip is transitioning') + } $(this.element).trigger(showEvent) - let isInTheDom = $.contains( + const isInTheDom = $.contains( this.element.ownerDocument.documentElement, this.element ) @@ -254,8 +263,8 @@ const Tooltip = (($) => { return } - let tip = this.getTipElement() - let tipId = Util.getUID(this.constructor.NAME) + const tip = this.getTipElement() + const tipId = Util.getUID(this.constructor.NAME) tip.setAttribute('id', tipId) this.element.setAttribute('aria-describedby', tipId) @@ -266,15 +275,17 @@ const Tooltip = (($) => { $(tip).addClass(ClassName.FADE) } - let placement = typeof this.config.placement === 'function' ? + const placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement - let attachment = this._getAttachment(placement) + const attachment = this._getAttachment(placement) + + const container = this.config.container === false ? document.body : $(this.config.container) $(tip) .data(this.constructor.DATA_KEY, this) - .appendTo(document.body) + .appendTo(container) $(this.element).trigger(this.constructor.Event.INSERTED) @@ -292,11 +303,12 @@ const Tooltip = (($) => { Util.reflow(tip) this._tether.position() - $(tip).addClass(ClassName.IN) + $(tip).addClass(ClassName.SHOW) - let complete = () => { - let prevHoverState = this._hoverState + const complete = () => { + const prevHoverState = this._hoverState this._hoverState = null + this._isTransitioning = false $(this.element).trigger(this.constructor.Event.SHOWN) @@ -306,6 +318,7 @@ const Tooltip = (($) => { } if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) { + this._isTransitioning = true $(this.tip) .one(Util.TRANSITION_END, complete) .emulateTransitionEnd(Tooltip._TRANSITION_DURATION) @@ -317,15 +330,19 @@ const Tooltip = (($) => { } hide(callback) { - let tip = this.getTipElement() - let hideEvent = $.Event(this.constructor.Event.HIDE) - let complete = () => { - if (this._hoverState !== HoverState.IN && tip.parentNode) { + const tip = this.getTipElement() + const hideEvent = $.Event(this.constructor.Event.HIDE) + if (this._isTransitioning) { + throw new Error('Tooltip is transitioning') + } + const complete = () => { + if (this._hoverState !== HoverState.SHOW && tip.parentNode) { tip.parentNode.removeChild(tip) } this.element.removeAttribute('aria-describedby') $(this.element).trigger(this.constructor.Event.HIDDEN) + this._isTransitioning = false this.cleanupTether() if (callback) { @@ -339,11 +356,15 @@ const Tooltip = (($) => { return } - $(tip).removeClass(ClassName.IN) + $(tip).removeClass(ClassName.SHOW) - if (Util.supportsTransitionEnd() && - ($(this.tip).hasClass(ClassName.FADE))) { + this._activeTrigger[Trigger.CLICK] = false + this._activeTrigger[Trigger.FOCUS] = false + this._activeTrigger[Trigger.HOVER] = false + if (Util.supportsTransitionEnd() && + $(this.tip).hasClass(ClassName.FADE)) { + this._isTransitioning = true $(tip) .one(Util.TRANSITION_END, complete) .emulateTransitionEnd(TRANSITION_DURATION) @@ -363,23 +384,21 @@ const Tooltip = (($) => { } getTipElement() { - return (this.tip = this.tip || $(this.config.template)[0]) + return this.tip = this.tip || $(this.config.template)[0] } setContent() { - let $tip = $(this.getTipElement()) + const $tip = $(this.getTipElement()) this.setElementContent($tip.find(Selector.TOOLTIP_INNER), this.getTitle()) - $tip - .removeClass(ClassName.FADE) - .removeClass(ClassName.IN) + $tip.removeClass(`${ClassName.FADE} ${ClassName.SHOW}`) this.cleanupTether() } setElementContent($element, content) { - let html = this.config.html + const html = this.config.html if (typeof content === 'object' && (content.nodeType || content.jquery)) { // content is a DOM node or a jQuery if (html) { @@ -420,21 +439,21 @@ const Tooltip = (($) => { } _setListeners() { - let triggers = this.config.trigger.split(' ') + const triggers = this.config.trigger.split(' ') triggers.forEach((trigger) => { if (trigger === 'click') { $(this.element).on( this.constructor.Event.CLICK, this.config.selector, - $.proxy(this.toggle, this) + (event) => this.toggle(event) ) } else if (trigger !== Trigger.MANUAL) { - let eventIn = trigger === Trigger.HOVER ? + const eventIn = trigger === Trigger.HOVER ? this.constructor.Event.MOUSEENTER : this.constructor.Event.FOCUSIN - let eventOut = trigger === Trigger.HOVER ? + const eventOut = trigger === Trigger.HOVER ? this.constructor.Event.MOUSELEAVE : this.constructor.Event.FOCUSOUT @@ -442,14 +461,19 @@ const Tooltip = (($) => { .on( eventIn, this.config.selector, - $.proxy(this._enter, this) + (event) => this._enter(event) ) .on( eventOut, this.config.selector, - $.proxy(this._leave, this) + (event) => this._leave(event) ) } + + $(this.element).closest('.modal').on( + 'hide.bs.modal', + () => this.hide() + ) }) if (this.config.selector) { @@ -463,9 +487,9 @@ const Tooltip = (($) => { } _fixTitle() { - let titleType = typeof this.element.getAttribute('data-original-title') + const titleType = typeof this.element.getAttribute('data-original-title') if (this.element.getAttribute('title') || - (titleType !== 'string')) { + titleType !== 'string') { this.element.setAttribute( 'data-original-title', this.element.getAttribute('title') || '' @@ -475,7 +499,7 @@ const Tooltip = (($) => { } _enter(event, context) { - let dataKey = this.constructor.DATA_KEY + const dataKey = this.constructor.DATA_KEY context = context || $(event.currentTarget).data(dataKey) @@ -493,15 +517,15 @@ const Tooltip = (($) => { ] = true } - if ($(context.getTipElement()).hasClass(ClassName.IN) || - (context._hoverState === HoverState.IN)) { - context._hoverState = HoverState.IN + if ($(context.getTipElement()).hasClass(ClassName.SHOW) || + context._hoverState === HoverState.SHOW) { + context._hoverState = HoverState.SHOW return } clearTimeout(context._timeout) - context._hoverState = HoverState.IN + context._hoverState = HoverState.SHOW if (!context.config.delay || !context.config.delay.show) { context.show() @@ -509,14 +533,14 @@ const Tooltip = (($) => { } context._timeout = setTimeout(() => { - if (context._hoverState === HoverState.IN) { + if (context._hoverState === HoverState.SHOW) { context.show() } }, context.config.delay.show) } _leave(event, context) { - let dataKey = this.constructor.DATA_KEY + const dataKey = this.constructor.DATA_KEY context = context || $(event.currentTarget).data(dataKey) @@ -555,7 +579,7 @@ const Tooltip = (($) => { } _isWithActiveTrigger() { - for (let trigger in this._activeTrigger) { + for (const trigger in this._activeTrigger) { if (this._activeTrigger[trigger]) { return true } @@ -589,10 +613,10 @@ const Tooltip = (($) => { } _getDelegateConfig() { - let config = {} + const config = {} if (this.config) { - for (let key in this.config) { + for (const key in this.config) { if (this.constructor.Default[key] !== this.config[key]) { config[key] = this.config[key] } @@ -607,11 +631,10 @@ const Tooltip = (($) => { static _jQueryInterface(config) { return this.each(function () { - let data = $(this).data(DATA_KEY) - let _config = typeof config === 'object' ? - config : null + let data = $(this).data(DATA_KEY) + const _config = typeof config === 'object' && config - if (!data && /destroy|hide/.test(config)) { + if (!data && /dispose|hide/.test(config)) { return } |
