Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery .tooltip() don't hide when hovering over tooltip?

I'm showing a jQuery UI Tooltip right in the middle of my element, when hovering. But the tooltip itself disappears when hovering over it. (propagation problem)

Element:

enter image description here

With tooltip:

enter image description here

So, when I then hover the tooltip itself, it disappears, due to a propagation problem, I suppose.

HTML:

<div class="bar-wrapper">
    <label class="bar-lbl active one" title="2013"><span>2013</span></label>

    <div class="bar" data-percent="90"></div>
    <div class="bar-rest-overlay" data-percent="10"></div>
</div>

<div class="bar-wrapper">
    <label class="bar-lbl active one" title="2014"><span>2014</span></label>

    <div class="bar" data-percent="80"></div>
    <div class="bar-rest-overlay" data-percent="20"></div>
</div>

Current code:

$('.bar-lbl').tooltip(
{
    tooltipClass: 'bar-tooltip',
    position:
    {
        my: 'center',
        at: 'center'
    }
});

Partial fix (but leaves tooltips permanently visible):

$('.bar-lbl').on('mouseleave',
function(e)
{
    e.stopImmediatePropagation();

}).tooltip(
{
    tooltipClass: 'bar-tooltip',
    position:
    {
        my: 'center',
        at: 'center'
    }
});

Not working:

$('body').on('hover', '.ui-tooltip',
function(e)
{
    e.stopImmediatePropagation();
});

UPDATE: Thanks to Trevor, I came to a close-solution. (it still leaves the last hovered tooltip visible when hovering out):

It seems, when hovering out the tooltip itself, it hides. But hovering out of the .bar-lbl element, the tooltip stays visible, unless I hover another .bar-lbl element.

The problem is in the on('mouseleave') event on my .bar-lbl. I need both lines, but they interfere with each other. (see comments)

$('.bar-lbl').on('mouseenter',
function(e)
{
    $('.bar-lbl').not($(this)).tooltip('close');   // Close all other tooltips

}).on('mouseleave',
function(e)
{
    e.stopImmediatePropagation();    // keeps tooltip visible when hovering tooltip itself
    $('.bar-lbl').tooltip('close');  // I need this, but it breaks the line above, causing the tooltip to flicker

}).tooltip(
{
    tooltipClass: 'bar-tooltip',
    position:
    {
        my: 'center',
        at: 'center'
    }
});

$('body').on('mouseleave', '.ui-tooltip',
function(e)
{
    $('.bar-lbl').tooltip('close');
});
like image 658
jlmmns Avatar asked Nov 08 '13 12:11

jlmmns


2 Answers

Just putting the first part of your code for reference.

$('.bar-lbl').tooltip(
    {
        tooltipClass: 'bar-tooltip',
        position:
    {
        my: 'center',
        at: 'center'
    }
});

$('.bar-lbl').on('mouseleave', function(e)
{
    e.stopImmediatePropagation();

}).tooltip(
{
    tooltipClass: 'bar-tooltip',
    position:
    {
        my: 'center',
        at: 'center'
    }
});

For the last part, change the not working part to the following which closes the tooltip on mouseleave.

$('body').on('mouseleave', '.ui-tooltip',
function(e)
{
    $('.bar-lbl').tooltip('close');    
});
like image 153
Trevor Avatar answered Nov 04 '22 02:11

Trevor


This is how I handled it. You add a marker class .tooltip-anchor to every element that should have a tooltip. You also add data-tooltip-content attribute which contains the selector of that anchor's tooltip content. Finally, to opt-in to hover keeping the tooltip open, you add .tooltip-is-hoverable to the anchor. The code prevents jQuery UI from closing the tooltip and instead manages its own closing timers.

HTML:

<span class="tooltip-anchor tooltip-is-hoverable"
      data-tooltip-content="#my-tooltip-content"
      >
  this has a tooltip <span>(this inner span won't have a second tooltip)</span>
</span>
<div id="my-tooltip-content">
  When your tooltips don't vanish:
  <a href="https://www.google.com/search?q=be+happy">you might feel</a>.
</div>

JS:

$(() => {
  $(".tooltip-anchor").each((index, element) => {
    let $anchor = $(element),
        contentSelector = $anchor.data("tooltip-content"),
        $content = $(contentSelector).detach();

    let timeoutId = null;
    function cancelClose() {
      if (timeoutId) {
        clearTimeout(timeoutId);
        timeoutId = null;
      }
    }
    function scheduleClose() {
      cancelClose();
      timeoutId = setTimeout(() => {
        $anchor.tooltip("close");
        timeoutId = null;
      }, 250)
    }

    let tooltipOptions = {
      content: () => $content,
      // Only the tooltip anchor should get a tooltip.  If we used "*", every child tag would
      //  also get a tooltip.
      items: ".tooltip-anchor",
      position: {
        my: "center top+10",
        at: "center bottom",
        collision: "flipfit",
      },
    };
    if ($anchor.is(".tooltip-is-hoverable")) {
      $.extend(tooltipOptions, {
        open: (e) => {
          let $anchor = $(e.target),
              contentSelector = $anchor.data("tooltip-content"),
              $content = $(contentSelector),
              $tooltip = $content.closest("[role='tooltip'],.ui-tooltip");
          $tooltip.on('mouseenter', cancelClose),
          $tooltip.on('mouseleave', scheduleClose);
        },
        tooltipClass: "hoverable-tooltip",
      });

      // Prevent jquery UI from closing the tooltip of an anchor with a hoverable tooltip.
      $anchor.on('mouseleave', (e) => {
        // Instead, schedule a close.
        scheduleClose();
        e.stopImmediatePropagation();
      });
    }
    $anchor.tooltip(tooltipOptions);
  });
});
like image 36
Carl G Avatar answered Nov 04 '22 02:11

Carl G