Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bootstrap Tooltip with manual trigger and selector option

I have a dynamic table, loaded with ajax. I want to show a tooltip when I hover the mouse over a row, but I want the tooltip to appear over a certain cell (with class .name) instead of above the entire row.

Also, using title function, I need to be able to get closest row id and return a custom template.

Here is my code:

<table class="table" id="myTable">
    <thead>
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Country</th>
            <th>Statistics</th>
        </tr>
    </thead>
    <tbody>
        <tr id="1">
            <td >1</td>
            <td class="name">Name #1</td>
            <td>United States of America</td>
            <td>100%</td>
        </tr>
        <tr id="2">
            <td >2</td>
            <td class="name">Name #2</td>
            <td>United States of America</td>
            <td>50%</td>
        </tr>
    </tbody>
</table>

Initialization:

$('#myTable').tooltip({
    container: 'body',
    html: true,
    selector: 'td.name',
    trigger: 'manual',
    title: function() {
        // here will be custom template
        var id = $(this).parent().atrr('id');
        return id;
    }
});

Attempt One : Demo in jsFiddle

$('#myTable')
    .on('mouseenter focusin', 'tbody > tr', function() {
        $(this).find('td.name').tooltip('show');
    })
    .on('mouseleave focusout', 'tbody > tr', function() {
        $(this).find('td.name').tooltip('hide');
    });

Attempt Two : Demo in jsFiddle

var tip;
$('#myTable')
    .on('mouseenter focusin', 'tbody > tr', function() {
        tip = $(this).find('.offer-name');
        tip.tooltip(hereAllTooltipOptions);
        tip.tooltip('show');
    })
    .on('mouseleave focusout', 'tbody > tr', function() {
        tip.tooltip('hide');
    });

But I wonder greatly over the performance of such a solution. So, the question is how to do it and do it better?

like image 802
Indy Avatar asked Jul 26 '14 16:07

Indy


1 Answers

The problem here is that you can't use the selector option when trigger is set to manual. The selector is used for delegation when bootstrap is handling the trigger events, but you've explicitly said that you'll be the one handling delegation, so it ignores the selector setting.

This means we gain nothing from pre-initializing with code like this:

$('.parent').tooltip({
    selector: '.child',
    trigger: 'manual'
})

It just says I want to set tooltips on .child elements, but don't do anything about it, because I'll be handling it later.

Which is fine, that's that what we wanted to do anyway when we used manual. We'll be the ones to dictate when the tooltip is shown or hidden.

Let's look at what a simple case of that would look like:

$('#myTable').on({
    'mouseenter': function() {
        $(this).find('td.name').tooltip('show');
    },
    'mouseleave': function() {
        $(this).find('td.name').tooltip('hide');
    }
},'tbody > tr');

Demo in js Fiddle

However, this won't work in this instance because we want to dynamically generate tooltips. When we call .tooltip('show') on a particular element, bootstrap looks at that element to see if it has been initialized or has a title. The above example works, because I've hard coded in a title, but how would we use this if we wanted to initialize this tooltip first?

Just Initialize on the fly, right before you show the tooltip, like this:

$('#myTable').on({
    'mouseenter': function() {
        $(this).find('td.name')
            .tooltip({
                container: 'body',
                html: true,
                trigger: 'manual',
                title: function() {
                    return this.parentNode.id;
                }
            }).tooltip('show');
    },
    'mouseleave': function() {
        $(this).find('td.name').tooltip('hide');
    }
},'tbody > tr');

So you don't incur the initialization cost on every hover, you can wrap the initialization in an if statement to check if it has already been initialized like this:

var $cell = $(this).find('td.name');
if (!$cell.data("bs.tooltip")) {
    $cell.tooltip({ /* options */ });
}
$cell.tooltip('show');

Demo in jsFiddle

like image 189
KyleMit Avatar answered Sep 30 '22 16:09

KyleMit