user1381806
user1381806

Reputation: 529

Bootstrap Tooltip - Hide when another tooltip is click

I hope someone can help.

I'm trying to hide the tooltip when another tooltip icon is clicked. It works but when I decide to click the last tooltip again it 'flashes' the tooltip.

var Hastooltip = $('.hastooltip');
HasTooltip.on('click', function(e) {
     e.preventDefault();
     HasTooltip.tooltip('hide');
}).tooltip({
     animation: true
}).parent().delegate('.close', 'click', function() {
     HasTooltip.tooltip('hide');
});

HTML

<a href="#" class="hastooltip" data-original-title="Lorem ipsum dolor sit amet, consectetur adipisicing elit.">
    <h3>Info 1</h3>
</a>

<a href="#" class="hastooltip" data-original-title="Lorem ipsum dolor sit amet, consectetur adipisicing elit.">
    <h3>Info 2</h3>
</a>

If it helps a following markup is added to the DOM when the user clicks on the button to display the tooltip.

<div class="tooltip"</div>

Upvotes: 38

Views: 72732

Answers (10)

smdhkv
smdhkv

Reputation: 187

I used class name to add tooltip and removed using class name. it's working.

Add Tooltip

$('.tooltips').tooltip({
      animation: true
      , container: 'body'
      , html: true
      , placement: 'auto'
      , trigger: 'focus hover'
  });

Hide Tooltip

$('.tooltips').tooltip('hide');

Upvotes: 0

Egli Becerra
Egli Becerra

Reputation: 1040

I will give you a good solution plus a bonus

        //save the tooltip in variable (change the selector to suit your tooltip)
        var $tooltips = $('a[data-toggle="tooltip"]');
        
        //initialise the tooltip with 'click' trigger  
        $tooltips.tooltip({
            animated: 'fade',
            placement: 'top',
            trigger: 'click',
            delay: { "show": 100, "hide": 100 }
        });
        
        //Here is the juicy bit: when a tooltip is opened it 
        //it creates an 'aria-describedby' with the id of the tooltip
        //opened we can leverage this to turn off all others but current

        $tooltips.on('click', function () {
            var toolTipId = $(this).attr('aria-describedby');
            $('.tooltip').not('#'+ toolTipId).tooltip('hide');
        });

        //But wait theres more! if you call now we chuck in a free close on X seconds event!
        $tooltips.on('shown.bs.tooltip', function (e) {
            //Auto hide after 7 seconds
            setTimeout(function () {
                $(e.target).tooltip('hide');
            }, 7000);
        });

        //call now! XD

Upvotes: 0

donbrae
donbrae

Reputation: 31

Re kiprainey’s answer, there is an issue in that once a tooltip has been hidden, it needs to be clicked twice to be shown again. I got around this by using tooltip('hide') instead of hide():

$(element).on('show.bs.tooltip', function() {
    // Only one tooltip should ever be open at a time
    $('.tooltip').not(this).tooltip('hide');
});

Upvotes: 3

I slightly modified the code of kiprainey

const $tooltip = $('[data-toggle="tooltip"]');
 $tooltip.tooltip({
   html: true,
   trigger: 'click',
   placement: 'bottom',
 });
 $tooltip.on('show.bs.tooltip', () => {
   $('.tooltip').not(this).remove();
 });

I use remove() instead of hide()

Upvotes: 6

dh-phuong
dh-phuong

Reputation: 11

$('[data-toggle=tooltip],[rel=tooltip]').tooltip({ 
        container: 'body' }).click(function () {
        $('.tooltip').not(this).hide();
    });

Upvotes: 1

Ketwaroo D. Yaasir
Ketwaroo D. Yaasir

Reputation: 424

I was looking for a solution to this problem as well and it seems to me that $('.tooltip').not(this).hide(); will bypass any bootstrap show, shown, hide or hidden events you may have attached to the trigger element. After some thought, I've come up the following code allows for somewhat more transparent handling of attached events.

Note: tested on firefox and chrome only but should work fine in theory.

$(document).ready(function() {

  $('[data-toggle="popover"]').popover();


  $(document).on('show.bs.popover', function(event) {
    // could use [data-toggle="popover"] instead
    // using a different selector allows to have different sets of single instance popovers.
    $('[data-popover-type="singleton"]').not(event.target).each(function(key, el) {
      $(el).popover('hide'); // this way everything gets propagated properly
    });
  });

  $(document).on('click', function(event) {
    // choose to close all popovers if clicking on anything but a popover element.
    if (!($(event.target).data('toggle') === "popover" /* the trigger buttons */ 
          || $(event.target).hasClass('popover') /* the popup menu */
          || $(event.target).parents('.popover[role="tooltip"]').length /* this one is a bit fiddly but also catches child elements of the popup menu. */ )) {
      
      $('[data-toggle="popover"]').popover('hide');
    }
  });


});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet" />



<button type="button" class="btn btn-danger" data-placement="bottom" data-toggle="popover" title="Popover One" data-content="Popover One Content. `focus` trigger still behaves as expected" data-trigger="focus" data-popover-type="singleton">Popover One</button>

<button type="button" class="btn btn-warning" data-placement="bottom" data-toggle="popover" title="Popover Two" data-content="Popover Two Content. for other triggers, clicking on content does not close popover" data-trigger="click" data-popover-type="singleton">Popover Two</button>

<button type="button" class="btn btn-success" data-placement="bottom" data-toggle="popover" title="Popover Three" data-content="Popover Three Content. clicking outside popover menu closes everything" data-trigger="click" data-popover-type="singleton">Popover Three</button>

fiddle example here: http://jsfiddle.net/ketwaroo/x6k1h7j4/

Upvotes: 1

kiprainey
kiprainey

Reputation: 3291

This can be handled more easily than the above answers indicate. You can do this with a single line of javascript in your show handler:

$('.tooltip').not(this).hide();

Here's a complete example. Change 'element' to match your selector.

$(element).on('show.bs.tooltip', function() {
    // Only one tooltip should ever be open at a time
    $('.tooltip').not(this).hide();
});

The same technique is suggested for closing popovers in this SO thread:

How can I close a Twitter Bootstrap popover with a click from anywhere (else) on the page?

Upvotes: 57

Eric
Eric

Reputation: 1

Thanks Jochen for the "Iphone" click on tooltip to close solution, exactly what I was looking for.

As for the original request (prevent multiple tooltip fonctionnality is an obvious need when you are asked to implement click tooltip instead of rollover ones), here is my take:

Just after , show: function () { add:

  // HACK BEGIN
  // Quick fix. Only one tooltip should be visible at all time.
  // prototype level property are accessible to all instances so we use one to track last opened tooltip (ie. current this).
  if ( (Tooltip.prototype.currentlyShownTooltip != null) || (Tooltip.prototype.currentlyShownTooltip != undefined) ) {
    // Close previously opened tooltip.
    if (Tooltip.prototype.currentlyShownTooltip != this) { // Conflict with toggle func. Re-show.
        Tooltip.prototype.currentlyShownTooltip.hide();
        Tooltip.prototype.currentlyShownTooltip = null
    }
  }
  // Keep track of the currently opened tooltip.
  Tooltip.prototype.currentlyShownTooltip = this
  // HACK END

Upvotes: 0

user694844
user694844

Reputation: 1187

You need to check if the tooltip is showing and toggle its visibility manually. This is one way of doing it.

$(function() {
  var HasTooltip = $('.hastooltip');
  HasTooltip.on('click', function(e) {
    e.preventDefault();
    var isShowing = $(this).data('isShowing');
    HasTooltip.removeData('isShowing');
    if (isShowing !== 'true')
    {
      HasTooltip.not(this).tooltip('hide');
      $(this).data('isShowing', "true");
      $(this).tooltip('show');
    }
    else
    {
      $(this).tooltip('hide');
    }

  }).tooltip({
    animation: true,
    trigger: 'manual'
  });
});

Upvotes: 15

Jochen
Jochen

Reputation: 882

I went into the same problem for regular tooltips. On an iPhone, they do not go away when clicking on the body (i.e. somewhere else).

My solution is that when you click on the tooltip itself, it hides. IMHO, this should be integrated in bootstrap distribution, because it is few code with a big effect.

When you have access to bootstrap sources, add

this.tip().click($.proxy(this.hide, this))

as the last line in method Tooltip.prototype.init in file tooltip.js:

Tooltip.prototype.init = function (type, element, options) {
this.enabled  = true
this.type     = type
this.$element = $(element)
this.options  = this.getOptions(options)

var triggers = this.options.trigger.split(' ')

for (var i = triggers.length; i--;) {
  var trigger = triggers[i]

  if (trigger == 'click') {
    this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
  } else if (trigger != 'manual') {
    var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focus'
    var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'

    this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
    this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
  }
}

this.options.selector ?
  (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
  this.fixTitle()

 // Hide tooltip when clicking on it. Useful for mobile devices like iPhone where eventOut
 // (see above) on $element is not triggered and you don't get rid of the tooltip anymore.
 this.tip().click($.proxy(this.hide, this))
  }

If you do not have the sources at hand, you can achieve the same effect with the following:

    $(function()
    {
        // Apply tooltips
        var hasTooltip = $("[data-toggle='tooltip']").tooltip();

        // Loop over all elements having a tooltip now.
        hasTooltip.each(function()
           {
               // Get the tooltip itself, i.e. the Javascript object
               var $tooltip = $(this).data('bs.tooltip');

               // Hide tooltip when clicking on it
               $tooltip.tip().click($.proxy($tooltip.hide, $tooltip))
           }
        );
    });

For me, that makes a good user experience on an iPhone: Click on the element to see the tooltip. Click on the tooltip that it goes away.

Upvotes: 3

Related Questions