jleggio
jleggio

Reputation: 1286

Bootstrap tooltips to stay open on hover

I have bootstrap tooltips set up on my webpage. When you roll over an image the tooltips show up, inside the tooltips I have a link, when I roll over the actually tooltip to click the link... it fades away.

My question (which I oddly could not seem to find an answer anywhere for) is how can I get tooltips to stay open when I hover over the actually tooltip itself.

I've seen and tried some solutions where you can set a delay, but I'd rather not go in that direction as I didn't like that effect.

Any help would be great, thanks!

Upvotes: 7

Views: 21625

Answers (8)

Denis P
Denis P

Reputation: 1

This is what worked in my case - slightly modified version of the first answer

    var originalLeave = $.fn.tooltip.Constructor.prototype._leave;
    $.fn.tooltip.Constructor.prototype._leave = function (event, context) {     
    if (!event) {
        originalLeave.call(this, event, context);
        return;
    }
    var self = this;
    var timeoutId;
    var container;
    if (self._timeout > 0) {
        timeoutId = self._timeout;
        originalLeave.call(this, event, context);
    } else {
        timeoutId = setTimeout(() => originalLeave.call(self, event), 200);
    }

    if (event.currentTarget) {
        container = $("#" + $(event.currentTarget).attr("aria-describedby"));
        container.one("mouseenter", function () {
            //We entered the actual popover, so we don"t want to call original leave method anymore
            clearTimeout(timeoutId);
            //Let"s monitor popover content instead
            container.one("mouseleave", function () {
                originalLeave.call(self, event, context);
            });
        });
      }
    };

Upvotes: 0

Stelios Tsallas
Stelios Tsallas

Reputation: 1

let tooltipTimer = false;
let isTooltipOpen = false;
let tooltipDelay = 100;

$(document).on('mouseover', '[data-bs-toggle=tooltip]', function(e) {
  $('.tooltip').tooltip('hide');
  
  $(e.currentTarget).tooltip({
    'trigger': 'manual',
    'html': true
  }).tooltip('show');
});

$(document).on('mouseleave', '[data-bs-toggle=tooltip]', function(e) {
  if (!isTooltipOpen) {
    tooltipTimer = setTimeout(function () { 
      $(e.currentTarget).tooltip('hide'); 
    }, tooltipDelay);
  }
});

$(document).on('mouseover', '.tooltip', function() {
  clearTooltipTimeout();
  
  isTooltipOpen = true;
});

$(document).on('mouseleave', '.tooltip', function(e) {
  tooltipTimer = setTimeout(function () { 
    $(e.currentTarget).tooltip('hide');     
  }, tooltipDelay);

  isTooltipOpen = false;
});

function clearTooltipTimeout()
{
  if (tooltipTimer) 
  {                            
    window.clearTimeout(tooltipTimer);
                                
    tooltipTimer = false;
  }
}
<!DOCTYPE html>
<html lang="en">
<head>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
</head>
<body>

<a data-bs-toggle="tooltip" title="Tooltip open on hover!">Tooltip</a>

</body>
</html>

Upvotes: 0

JP Garza
JP Garza

Reputation: 270

This worked for me:

$('[data-toggle="tooltip"]').tooltip({
    trigger: "manual"
});

$('[data-toggle="tooltip"]').on('mouseleave', function () {
    $(this).tooltip('hide');
});

$('[data-toggle="tooltip"]').on('mouseenter', function () {
    $(this).tooltip('show');
});

$('[data-toggle="tooltip"]').on('click', function () {
    $(this).tooltip('hide');
});

Upvotes: 1

Simple Code
Simple Code

Reputation: 2574

$(document).ready(function(){

    $(document).on("mouseover", "#myLink", (event) => {

        $(event.target).tooltip(
            {
                trigger: 'manual',
                delay: { "hide": 500 }
            }).tooltip("show");
    });

    var isOver = false;

    $(document).on("mouseleave", "#myLink", (event) => {
        setTimeout(function () { }, 1000);

        if (!isOver)
            setTimeout(function () { $('#myLink').tooltip('hide'); }, 500);
    });

    $(document).on("mouseover", ".tooltip", (event) => {

        isOver = true;
    });

    $(document).on("mouseleave", ".tooltip", (event) => {

        setTimeout(function () { $('#myLink').tooltip('hide'); }, 500);
    });
    
});
<!DOCTYPE html>
<html lang="en">
<head>
  <title>Bootstrap Example</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
</head>
<body>

<a href="#" id="myLink" data-toggle="tooltip" title="Stay over me!">Hover over me</a>


</body>
</html>

Upvotes: 1

wolverineo250kr
wolverineo250kr

Reputation: 21

Thу way i did

  $(document).ready(function () {
        $('[data-toggle="tooltip"]').tooltip({
            trigger: "manual"
        });

        $('body').on('mouseleave', '.tooltip', function () {
            $('[data-toggle="tooltip"]').tooltip('hide');
        });

        $('[data-toggle="tooltip"] > i').on('mouseenter', function () {
            $('[data-toggle="tooltip"]').tooltip('show');
        });

        $('[data-toggle="tooltip"]').on('click', function () {
            $(this).tooltip('show');
        }); });

Upvotes: 2

I did it this way.

I'm triggering the tooltip on a link - so the a would have to be replaced to the relevant element:

Initialize the tooltip:

    $(document).ready(function() {
      $('a').tooltip();
    })

Keep Tooltip open on mouseover + add a helper class on first mouseover (the tooltip alway triggered two mouseover events in my case - so I had to be sure only to add .active in the first go)

    $(document).on('mouseover','.tooltip', function() {
      var tooltipTrigger = $('a[aria-describedby="' + $(this).attr('id') + '"');
      if(! $(tooltipTrigger).hasClass('active')) {
        $(tooltipTrigger).tooltip('show').addClass('active');            
      }
    });

Hide the corresponding tooltip when mouseout happens... this uses tooltip-inner to trigger, because the little arrow of the tooltip, which still belongs to .tooltip, can lead to a case, where you might go out of the tooltip with the cursor, but not far enough, and then the tooltips remains open...

    $(document).on('mouseout','.tooltip-inner', function() {
      $('a.active').tooltip('hide').removeClass('active');
    });

Upvotes: 2

thatzprem
thatzprem

Reputation: 4767

Try this. This could help.

tooltip-trigger="focus manual"

Upvotes: 0

user2265668
user2265668

Reputation: 101

var originalLeave = $.fn.tooltip.Constructor.prototype.leave;
$.fn.tooltip.Constructor.prototype.leave = function(obj){
  var self = obj instanceof this.constructor ?
    obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
  var container, timeout;

  originalLeave.call(this, obj);

  if(obj.currentTarget) {
    container = $(obj.currentTarget).siblings('.tooltip')
    timeout = self.timeout;
    container.one('mouseenter', function(){
      //We entered the actual popover – call off the dogs
      clearTimeout(timeout);
      //Let's monitor popover content instead
      container.one('mouseleave', function(){
        $.fn.tooltip.Constructor.prototype.leave.call(self, self);
      });
    })
  }
};


$('body').tooltip({ selector: '[data-toggle]', trigger: 'click hover', placement: 'bottom auto', delay: {show: 50, hide: 400}});

Upvotes: 10

Related Questions