291

I'm using Twitter bootstrap tooltips with javascript like the following:

$('a[rel=tooltip]').tooltip();

My markup looks like this:

<a rel="tooltip" title="Not implemented" class="btn"><i class="icon-file"></i></a>

This works fine, but I add <a> elements dynamically and the tooltips aren't showing up for those dynamic elements. I know it's because I only bind .tooltip() once when the document is finished loaded with the typical jquery $(document).ready(function() functionality.

How can I bind this to dynamically created elements? Usually I would do this via the jquery live() method. However, what is the event that I use to bind? I'm just not sure how to hook up the bootstrap .tooltip() with jquery .live().

I've found one way to make this work is something like this:

/* Add new 'rows' when plus sign is clicked */
$("a.add").live('click', function () {
    var clicked_li = $(this).parent('li');
    var clone = clicked_li.clone();

    clone.find(':input').each(function() {
        $(this).val('');
    });

    clicked_li.after(clone);
    $('a[rel=tooltip]').tooltip();
});

This works, but seems kind of hackish. I'm also calling the exact same .tooltip() line in the $(ready) call. So, do the elements that exist when the page first loads and match that selector end up with the tooltip twice?

I don't see any problems with this approach. I'm just looking for a best practice or understanding of the behavior.

durden2.0
  • 9,222
  • 9
  • 44
  • 57
  • hmm good question, will this help? https://github.com/twitter/bootstrap/issues/2374 – Tim Mar 31 '12 at 19:16
  • That's an interesting read, but I'm only wanting a single type of tooltip. I just want to make sure any dynamically added elements that match the tooltip selector get added, which isn't the case. – durden2.0 Apr 01 '12 at 02:44
  • 3
    Great question. Seems like an oversite on the part of twitter. – Luke The Obscure May 22 '12 at 18:26
  • 1
    @durden2.0 How did Christians answer work for you? Care to accept as correct? – Ruslans Uralovs Aug 22 '12 at 10:13
  • 3
    Not really related to your question but... I find it bad style to hijack the `rel` attribute. This is non-semantic and was originated over a decade ago as a hack. Nowadays, every single browser going back several years supports `data-*` attributes and there's no more reason not to use them. – T Nguyen Feb 11 '14 at 15:41

8 Answers8

521

Try this one:

$('body').tooltip({
    selector: '[rel=tooltip]'
});
Christian Strang
  • 8,470
  • 5
  • 42
  • 53
  • 4
    Great. This is the correct answer, because it's basically the substitute of live/on. – Mahn Jul 03 '12 at 21:57
  • 3
    @CalvinL [If a selector is provided, tooltip objects will be delegated to the specified targets.](http://twitter.github.com/bootstrap/javascript.html#tooltips) – Terry Jul 20 '12 at 14:20
  • This is also the solution for elements added after page load by an ajax call. – 12Bo Aug 03 '12 at 20:33
  • 5
    What I don't like about this solution is that you can't have multiple configuration of tooltips. For example, it doesn't work if you have tooltips that are placed on top and others that are placed on bottom. – barbolo Aug 29 '12 at 03:31
  • 7
    @barbolo, simply use different selectors for different configurations. This is the right solution. Btw, it works also with Popover. – Enrico Carlesso Sep 19 '12 at 10:22
  • 1
    @EnricoCarlesso how do you use different selectors for different configurations? I tried: $("body .mySelector").popover({..}) but that didn't work. and also multiple $("body").popover({selector:".mySelector1"}); $("body").popover({selector:".mySelector2"}); neither worked – B Z Mar 28 '13 at 19:42
  • This works well, but in my Google Maps (jquery-ui-map) application, using 'body' as the selector was causing "something squirrelly" to happen within the map. I used an internal div instead, e.g. `$('#map')`, and my problem seemed fixed. This might also help readers who have the same question as @BZ. – Jeremy Carlson Sep 26 '13 at 16:01
  • @EnricoCarlesso, I am also trying to get different configurations working, but they do not. Performing the `$("body").tooltip()` call more than once seems to overwrite the previous one, even if the selector is different. – John Washam Feb 25 '14 at 21:16
  • 2
    Well, this answer is quite old, @JohnDubya, not sure if anything has changed and which bootstrap you are using. Anyway, I whould say that you should delegate the configuration to the data-whatever field in the html field. Take a look at this fiddle: http://jsfiddle.net/carlesso/4Qjcr/ – Enrico Carlesso Feb 25 '14 at 21:46
  • Oh my gosh, how simple. It's always the simple method you forget about. Sigh. Thank you, Enrico, the data-placement attribute should do nicely, instead of setting multiple configurations. SMH – John Washam Feb 26 '14 at 22:09
  • As of JQuery 1.10, "selector:" changed to "items:". http://api.jqueryui.com/tooltip/ – Jonathan Dautrich Apr 30 '14 at 05:51
  • 19
    bootstrap 3 use $('body').tooltip({selector:'[data-toggle=tooltip]'}); – MERT DOĞAN Oct 20 '14 at 11:14
  • console error TypeError: c is undefined.but working fine – Bugfixer Feb 09 '16 at 09:32
  • Anyone know if there is a performance hit using this technique? – Kris Jun 20 '18 at 09:17
158

If you have multiple tooltip configurations that you want to initialise, this works well for me.

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

You can then set the property on individual elements using data attributes.

Nobody
  • 117
  • 2
  • 12
rohitmishra
  • 8,739
  • 7
  • 33
  • 34
17

For me, only catching the mouseenter event was a bit buggy, and the tooltip was not showing/hiding properly. I had to write this, and it is now working perfectly:

$(document).on('mouseenter','[rel=tooltip]', function(){
    $(this).tooltip('show');
});

$(document).on('mouseleave','[rel=tooltip]', function(){
    $(this).tooltip('hide');
});
Paola Cerioli
  • 741
  • 7
  • 7
  • 3
    This was very helpful insite as to why .on('hover') wouldn't work right. – Adam Aug 16 '12 at 13:03
  • This was all I needed to use for my implementation of using handlebars.js. If I wasn't using handlebars.js, the accepted answer also worked. – HPWD Sep 20 '18 at 00:19
  • This is how I used to do this but you lose a lot of options like hover delays that you would need to implement manually with this I think. – DavidScherer Feb 08 '19 at 19:25
15

I've posted longer answer here: https://stackoverflow.com/a/20877657/207661

TL;DR: You need only one line of code that runs in document ready event:

$(document.body).tooltip({ selector: "[title]" });

Other more complicated code suggested in other answers don't seem necessary (I've tested this with Bootstrap 3.0).

Community
  • 1
  • 1
Shital Shah
  • 63,284
  • 17
  • 238
  • 185
  • 1
    This is the best answer. – Chris Marisic Jan 22 '16 at 19:23
  • This worked for my case. I used a table with Tablesorter 2.26.2 and populated values via Ajax call. Problem was that the html tooltip was shown as HTML text instead of rendered output. This is the only solution worked for me in the first go. +1 and lot of thanks! – Anurag Mar 01 '17 at 12:25
8

For me, this js reproduces the same problem that happens with Paola

My solution:

$(document.body).tooltip({selector: '[title]'})
.on('click mouseenter mouseleave','[title]', function(ev) {
    $(this).tooltip('mouseenter' === ev.type? 'show': 'hide');
});
Community
  • 1
  • 1
Dg Jacquard
  • 1,090
  • 10
  • 10
2

Rather than search it in full Body. One could just use dynamic title option already available in such scenarios I think:

$btn.tooltip({
  title: function(){
    return $(this).attr('title');
  }
});
Jaskaran Singh
  • 2,392
  • 24
  • 39
1

I found a combination of these answers gave me the best outcome - allowing me to still position the tooltip and attach it to the relevant container:

$('body').on('mouseenter', '[rel=tooltip]', function(){
  var el = $(this);
  if (el.data('tooltip') === undefined) {
    el.tooltip({
      placement: el.data("placement") || "top",
      container: el.data("container") || false
    });
  }
  el.tooltip('show');
});

$('body').on('mouseleave', '[rel=tooltip]', function(){
  $(this).tooltip('hide');
});

Relevant HTML:

<button rel="tooltip" class="btn" data-placement="bottom" data-container=".some-parent" title="Show Tooltip">
    <i class="icon-some-icon"></i>
</button>
mattgi
  • 712
  • 1
  • 7
  • 11
1

In Bootstrap 5, which doesn't use jQuery, you can do this:

const btn = document.createElement('button');
btn.innerHTML = 'Click me';
btn.dataset['toggle'] = 'tooltip';
btn.dataset['placement'] = 'top';
btn.title = 'Your Tooltip Here';
new bootstrap.Tooltip(btn);

document.getElementById('parent').appendChild(btn);
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-CuOF+2SnTUfTwSZjCXf01h7uYhfOBuxIhGKPbfEJ3+FqH/s6cIFN9bGr1HmAg4fQ" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-popRpmFF9JQgExhfw5tZT4I9/CI5e2QcuUZPOVXb1m7qUmeR2b50u+YFEYe1wgzy" crossorigin="anonymous"></script>
<div id="parent"></div>
Webucator
  • 2,397
  • 24
  • 39