1

Suppose we have a function generateTooltip() that generates and returns the html of a tooltip for DOM element el. How can I get this tooltip to be generated and shown on demand (hover)?

Background

I suppose one could generate the tooltip beforehand and assign the pre-generated html as a tooltip to el, but I want the generation to be lazy as my generateTooltip(i,j) defines many rich tooltips for the cells of a large table.

(Currently I'm only using jQuery but would add a library if necessary.)

Edit

Emphasis added to prevent further misunderstanding. The tooltip shouldn't be pre-generated on page load.

Community
  • 1
  • 1
Museful
  • 6,711
  • 5
  • 42
  • 68

2 Answers2

1

Hope this is what you're looking for...

$("table td.hoverTarget").hover(function(){
    var hovered = $(this);
    var cellIndex = hovered.eq();
    var rowIndex =  hovered.parent().eq();
    if(hovered.children(".tooltipClass").length) {
         hovered.children(".tooltipClass").fadeIn();
    }
    else {
        activeTooltip = generateTooltip(rowIndex,cellIndex);
        hovered.append(activeTooltip);
    }
}, function(){
     var hovered = $(this);
     hovered.children(".tooltipClass").fadeOut();
});

Here's a fiddle ==> FIDDLE

Sampgun
  • 2,822
  • 1
  • 21
  • 38
  • 1
    Why don't you use Bootstrap's tooltips then? – Sampgun Jun 11 '17 at 16:08
  • Because bootstrap library is too heavy for just this, and from what I can see, it doesn't support a callback to generate the tooltip dynamically. So it wouldn't help me. – Museful Jun 11 '17 at 16:50
  • Anyway I just want to let you know that you can customize the bootstrap.js build and get only what you need. http://getbootstrap.com/customize/#plugins – Sampgun Jun 11 '17 at 17:41
0

This answer works on cells that are not yet generated when this code is run. (jQuery .on() does not support hover events.) It also places the tooltip outside (below) the relevant cell, in front of other cells/content.

$('table').on({
    mouseover: function(){
        var cell = $(this);
        if(cell.data('timeout') !== undefined){
            clearTimeout(cell.data('timeout'));
            cell.removeData('timeout');
            showTooltip(cell, false);
        }
        var timeout = setTimeout(function(){
            showTooltip(cell, true);
        }, 300); // tooltip delay
        cell.data('timeout',timeout);
    },
    mouseleave: function(){
        var cell = $(this);
        if(cell.data('timeout') !== undefined){
            clearTimeout(cell.data('timeout'));
            cell.removeData('timeout');
        }
        showTooltip(cell, false);
    }
}, 'td.hoverTarget');

function showTooltip(cell, show){
    if(show){
        if(cell.children('.tooltipContainer').length == 0){
            var j = cell.parent().children('td').index(cell);
            var i = cell.parent().index();
            var tooltipContent = generateTooltip(i,j);
            if(tooltipContent){
                var tooltip = $('<div></div>').addClass('cellTooltip').append(tooltipContent);
                var ttc = $('<div></div>').addClass('tooltipContainer').append(tooltip);
                cell.append(ttc);
                tooltip.hide();
            }
        }
        cell.find('.cellTooltip').fadeIn();
    } else {
        cell.find('.cellTooltip').fadeOut();                    
    }
}

function generateTooltip(i, j){
    // ...
    return "HTML for large tooltip.";
}

CSS:

table td.hoverTarget>div.tooltipContainer {
    position: relative; /* see https://stackoverflow.com/a/6040258/827280. */
}

table td.hoverTarget>div.tooltipContainer>.cellTooltip {
    background-color: white;
    border: 1px solid black;
    position: absolute;
    top: 30px;
    z-index: 1;
}
Museful
  • 6,711
  • 5
  • 42
  • 68