66import Vue from '../../../utils/vue'
77import getScopId from '../../../utils/get-scope-id'
88import looseEqual from '../../../utils/loose-equal'
9+ import noop from '../../../utils/noop'
910import { arrayIncludes , concat , from as arrayFrom } from '../../../utils/array'
1011import {
1112 isElement ,
@@ -34,7 +35,6 @@ import {
3435import { keys } from '../../../utils/object'
3536import { warn } from '../../../utils/warn'
3637import { BvEvent } from '../../../utils/bv-event.class'
37-
3838import { BVTooltipTemplate } from './bv-tooltip-template'
3939
4040const NAME = 'BVTooltip'
@@ -203,7 +203,7 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({
203203 this . $_hoverState = ''
204204 this . $_visibleInterval = null
205205 this . $_enabled = ! this . disabled
206- this . $_noop = ( ) => { }
206+ this . $_noop = noop . bind ( this )
207207
208208 // Destroy ourselves when the parent is destroyed
209209 if ( this . $parent ) {
@@ -236,18 +236,14 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({
236236 // Remove all handler/listeners
237237 this . unListen ( )
238238 this . setWhileOpenListeners ( false )
239-
240- // Clear any timeouts/Timers
241- clearTimeout ( this . $_hoverTimeout )
242- this . $_hoverTimeout = null
243-
239+ // Clear any timeouts/intervals
240+ this . clearHoverTimeout ( )
241+ this . clearVisibilityInterval ( )
242+ // Destroy the template
244243 this . destroyTemplate ( )
245- this . restoreTitle ( )
246244 } ,
247245 methods : {
248- //
249- // Methods for creating and destroying the template
250- //
246+ // --- Methods for creating and destroying the template ---
251247 getTemplate ( ) {
252248 // Overridden by BVPopover
253249 return BVTooltipTemplate
@@ -273,7 +269,6 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({
273269 } ,
274270 createTemplateAndShow ( ) {
275271 // Creates the template instance and show it
276- // this.destroyTemplate()
277272 const container = this . getContainer ( )
278273 const Template = this . getTemplate ( )
279274 const $tip = ( this . $_tip = new Template ( {
@@ -323,19 +318,24 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({
323318 // then emit the `hidden` event once it is fully hidden
324319 // The `hook:destroyed` will also be called (safety measure)
325320 this . $_tip && this . $_tip . hide ( )
321+ // Clear out any stragging active triggers
322+ this . clearActiveTriggers ( )
323+ // Reset the hover state
324+ this . $_hoverState = ''
326325 } ,
326+ // Destroy the template instance and reset state
327327 destroyTemplate ( ) {
328- // Destroy the template instance and reset state
329328 this . setWhileOpenListeners ( false )
330- clearTimeout ( this . $_hoverTimeout )
331- this . $_hoverTimout = null
329+ this . clearHoverTimeout ( )
332330 this . $_hoverState = ''
333331 this . clearActiveTriggers ( )
334332 this . localPlacementTarget = null
335333 try {
336334 this . $_tip && this . $_tip . $destroy ( )
337335 } catch { }
338336 this . $_tip = null
337+ this . removeAriaDescribedby ( )
338+ this . restoreTitle ( )
339339 this . localShow = false
340340 } ,
341341 getTemplateElement ( ) {
@@ -355,13 +355,10 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({
355355 } )
356356 }
357357 } ,
358- //
359- // Show and Hide handlers
360- //
358+ // --- Show/Hide handlers ---
359+ // Show the tooltip
361360 show ( ) {
362- // Show the tooltip
363361 const target = this . getTarget ( )
364-
365362 if (
366363 ! target ||
367364 ! contains ( document . body , target ) ||
@@ -375,38 +372,29 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({
375372 // we exit without showing
376373 return
377374 }
378-
375+ // If tip already exists, exit early
379376 if ( this . $_tip || this . localShow ) {
380- // If tip already exists, exit early
381377 /* istanbul ignore next */
382378 return
383379 }
384-
385380 // In the process of showing
386381 this . localShow = true
387-
388382 // Create a cancelable BvEvent
389383 const showEvt = this . buildEvent ( 'show' , { cancelable : true } )
390384 this . emitEvent ( showEvt )
385+ // Don't show if event cancelled
391386 /* istanbul ignore next: ignore for now */
392387 if ( showEvt . defaultPrevented ) {
393- // Don't show if event cancelled
394388 // Destroy the template (if for some reason it was created)
395389 /* istanbul ignore next */
396390 this . destroyTemplate ( )
397- // Clear the localShow flag
398- /* istanbul ignore next */
399- this . localShow = false
400391 /* istanbul ignore next */
401392 return
402393 }
403-
404394 // Fix the title attribute on target
405395 this . fixTitle ( )
406-
407396 // Set aria-describedby on target
408397 this . addAriaDescribedby ( )
409-
410398 // Create and show the tooltip
411399 this . createTemplateAndShow ( )
412400 } ,
@@ -433,11 +421,6 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({
433421
434422 // Tell the template to hide
435423 this . hideTemplate ( )
436- // TODO: The following could be added to `hideTemplate()`
437- // Clear out any stragging active triggers
438- this . clearActiveTriggers ( )
439- // Reset the hover state
440- this . $_hoverState = ''
441424 } ,
442425 forceHide ( ) {
443426 // Forcefully hides/destroys the template, regardless of any active triggers
@@ -450,8 +433,7 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({
450433 // This is also done in the template `hide` evt handler
451434 this . setWhileOpenListeners ( false )
452435 // Clear any hover enter/leave event
453- clearTimeout ( this . hoverTimeout )
454- this . $_hoverTimeout = null
436+ this . clearHoverTimeout ( )
455437 this . $_hoverState = ''
456438 this . clearActiveTriggers ( )
457439 // Disable the fade animation on the template
@@ -464,49 +446,42 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({
464446 enable ( ) {
465447 this . $_enabled = true
466448 // Create a non-cancelable BvEvent
467- this . emitEvent ( this . buildEvent ( 'enabled' , { } ) )
449+ this . emitEvent ( this . buildEvent ( 'enabled' ) )
468450 } ,
469451 disable ( ) {
470452 this . $_enabled = false
471453 // Create a non-cancelable BvEvent
472- this . emitEvent ( this . buildEvent ( 'disabled' , { } ) )
454+ this . emitEvent ( this . buildEvent ( 'disabled' ) )
473455 } ,
474- //
475- // Handlers for template events
476- //
456+ // --- Handlers for template events ---
457+ // When template is inserted into DOM, but not yet shown
477458 onTemplateShow ( ) {
478- // When template is inserted into DOM, but not yet shown
479459 // Enable while open listeners/watchers
480460 this . setWhileOpenListeners ( true )
481461 } ,
462+ // When template show transition completes
482463 onTemplateShown ( ) {
483- // When template show transition completes
484464 const prevHoverState = this . $_hoverState
485465 this . $_hoverState = ''
486466 if ( prevHoverState === 'out' ) {
487467 this . leave ( null )
488468 }
489469 // Emit a non-cancelable BvEvent 'shown'
490- this . emitEvent ( this . buildEvent ( 'shown' , { } ) )
470+ this . emitEvent ( this . buildEvent ( 'shown' ) )
491471 } ,
472+ // When template is starting to hide
492473 onTemplateHide ( ) {
493- // When template is starting to hide
494474 // Disable while open listeners/watchers
495475 this . setWhileOpenListeners ( false )
496476 } ,
477+ // When template has completed closing (just before it self destructs)
497478 onTemplateHidden ( ) {
498- // When template has completed closing (just before it self destructs)
499- // TODO:
500- // The next two lines could be moved into `destroyTemplate()`
501- this . removeAriaDescribedby ( )
502- this . restoreTitle ( )
479+ // Destroy the template
503480 this . destroyTemplate ( )
504481 // Emit a non-cancelable BvEvent 'shown'
505482 this . emitEvent ( this . buildEvent ( 'hidden' , { } ) )
506483 } ,
507- //
508- // Utility methods
509- //
484+ // --- Utility methods ---
510485 getTarget ( ) {
511486 // Handle case where target may be a component ref
512487 let target = this . target ? this . target . $el || this . target : null
@@ -566,6 +541,18 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({
566541 const target = this . getTarget ( )
567542 return this . isDropdown ( ) && target && select ( DROPDOWN_OPEN_SELECTOR , target )
568543 } ,
544+ clearHoverTimeout ( ) {
545+ if ( this . $_hoverTimeout ) {
546+ clearTimeout ( this . $_hoverTimeout )
547+ this . $_hoverTimeout = null
548+ }
549+ } ,
550+ clearVisibilityInterval ( ) {
551+ if ( this . $_visibleInterval ) {
552+ clearInterval ( this . $_visibleInterval )
553+ this . $_visibleInterval = null
554+ }
555+ } ,
569556 clearActiveTriggers ( ) {
570557 for ( const trigger in this . activeTrigger ) {
571558 this . activeTrigger [ trigger ] = false
@@ -619,9 +606,7 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({
619606 removeAttr ( target , 'data-original-title' )
620607 }
621608 } ,
622- //
623- // BvEvent helpers
624- //
609+ // --- BvEvent helpers ---
625610 buildEvent ( type , opts = { } ) {
626611 // Defaults to a non-cancellable event
627612 return new BvEvent ( type , {
@@ -644,20 +629,16 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({
644629 }
645630 this . $emit ( evtName , bvEvt )
646631 } ,
647- //
648- // Event handler setup methods
649- //
632+ // --- Event handler setup methods ---
650633 listen ( ) {
651634 // Enable trigger event handlers
652635 const el = this . getTarget ( )
653636 if ( ! el ) {
654637 /* istanbul ignore next */
655638 return
656639 }
657-
658640 // Listen for global show/hide events
659641 this . setRootListener ( true )
660-
661642 // Set up our listeners on the target trigger element
662643 this . computedTriggers . forEach ( trigger => {
663644 if ( trigger === 'click' ) {
@@ -712,14 +693,13 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({
712693 // On-touch start listeners
713694 this . setOnTouchStartListener ( on )
714695 } ,
696+ // Handler for periodic visibility check
715697 visibleCheck ( on ) {
716- // Handler for periodic visibility check
717- clearInterval ( this . $_visibleInterval )
718- this . $_visibleInterval = null
698+ this . clearVisibilityInterval ( )
719699 const target = this . getTarget ( )
720700 const tip = this . getTemplateElement ( )
721701 if ( on ) {
722- this . visibleInterval = setInterval ( ( ) => {
702+ this . $_visibleInterval = setInterval ( ( ) => {
723703 if ( tip && this . localShow && ( ! target . parentNode || ! isVisible ( target ) ) ) {
724704 // Target element is no longer visible or not in DOM, so force-hide the tooltip
725705 this . forceHide ( )
@@ -762,9 +742,7 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({
762742 target . __vue__ [ on ? '$on' : '$off' ] ( 'shown' , this . forceHide )
763743 }
764744 } ,
765- //
766- // Event handlers
767- //
745+ // --- Event handlers ---
768746 handleEvent ( evt ) {
769747 // General trigger event handler
770748 // target is the trigger element
@@ -884,14 +862,14 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({
884862 this . $_hoverState = 'in'
885863 return
886864 }
887- clearTimeout ( this . hoverTimeout )
865+ this . clearHoverTimeout ( )
888866 this . $_hoverState = 'in'
889867 if ( ! this . computedDelay . show ) {
890868 this . show ( )
891869 } else {
892870 // Hide any title attribute while enter delay is active
893871 this . fixTitle ( )
894- this . hoverTimeout = setTimeout ( ( ) => {
872+ this . $_hoverTimeout = setTimeout ( ( ) => {
895873 /* istanbul ignore else */
896874 if ( this . $_hoverState === 'in' ) {
897875 this . show ( )
@@ -917,12 +895,12 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({
917895 if ( this . isWithActiveTrigger ) {
918896 return
919897 }
920- clearTimeout ( this . hoverTimeout )
898+ this . clearHoverTimeout ( )
921899 this . $_hoverState = 'out'
922900 if ( ! this . computedDelay . hide ) {
923901 this . hide ( )
924902 } else {
925- this . $hoverTimeout = setTimeout ( ( ) => {
903+ this . $_hoverTimeout = setTimeout ( ( ) => {
926904 if ( this . $_hoverState === 'out' ) {
927905 this . hide ( )
928906 }
0 commit comments