Home > other >  jQuery tooltip not working on dynamically loaded HTML content
jQuery tooltip not working on dynamically loaded HTML content

Time:04-20

This code works well but stops working in case of dynamically loaded HTML contents. The JS code is given below, load function loads HTML from another page and then shows it in a modal window, in this modal window I need the tooltip to work.

$(document).ready(function() {
  $(".content span").tooltip({
    track: true,
    open: function(event, ui) {
      var id = this.id;
      var pid = $(this).attr('data-id');
      $.ajax({
        url: 'tooltip.php',
        type: 'get',
        data: {
          pid: pid
        },
        cache: true,
        success: function(response) {
          $("#"   id).tooltip('option', 'content', response);
        }
      });
    }
  });

  $(".content span").mouseout(function() {
    $(this).attr('title', 'Please wait...');
    $(this).tooltip();
    $('.ui-tooltip').hide();
  });
});

function load(id) {
$.ajax({
url: 'modal.php',
type: 'post',
data: {id: id},
success: function(response){ 
$('.modal-body').html(response);
$('#itiModal').modal('show'); 
}
});
}

JS script loads content from a PHP code, which is used to generate content where the tooltip is required
Sample HTML from load function

Welcome<b>Day 1</b> Cola Pepsi, Mountain Dew <div ><span title="Loading..." data-id="1" id="info_1">Pepsi</span></div> , <div ><span title="Loading..." data-id="2" id="info_2">Cola </span></div> , DINNER<br/><b>Day 2</b> Mountain Dew<br/>

Below sample HTML content from where tooltip should fetch the content

Others<br/><b></b><br/>0<br/>0

Though there is no error, the code does not work and the tooltip shows only Loading...
How to make this work with content which is loaded dynamically ?

in simple -> A button on index.php loads content from modal.php, and on this content I want tooltip, the tooltip should load content from tooltip.php?pid=

CodePudding user response:

Can you try to push this line to your code.

$('body').tooltip({selector: '.content span'});

Right after

$(document).ready(function() {
    // push the above line here
    ... your current code

}

CodePudding user response:

As described in the comments, the problem is jQuery selectors only match page elements that exist at page load. $(".content span").tooltip() will only initialise tooltips for spans that exist inside .content at page load. If you inject new spans later, they're not included, and that jQuery selector and tooltip initialisation is not applied to them.

Here's a super-simplified version of your code which demonstrates the problem:

$(document).ready(function() {
  // Basic tooltip will work for any span inside .content AT PAGE LOAD.
  $(".content span").tooltip();
  
  // Simulate adding some HTML to the page after load, like your AJAX does
  $('button').on('click', function() {
      $('.modal-body').html('<p>This <span title="Added after page load, tooltip does not work">Span2</span> was added after page load, the jQuery selector will not match it, so tooltips will not work.</p>');
  });
});
span {
    color:blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css">

<div >
    <p>This span exists at page load and its tooltip works:
        <span title="Yes it works">Span1</span>
    </p>
    
    <p>Click the button below to add some HTML here after page load.</p>
    <div ></div>
</div>

<button>Add some HTML after page load</button>

There are a few options to work around this. Maybe simplest is to use the (apparently undocumented?) selector tooltip option:

$(".content").tooltip({
    selector: 'span'
});

This works something like jQuery's selector context, which is one way of handling the same problem for attaching event handlers to dynamically added content. The handler is initialised on a parent element which exists at page load, but whenever triggered, is filtered to only match the elements specified. The key is the filtering happens dynamically, whenever the main handler is triggered, not just at page load.

So in this case, we initialise .tooltip() on your .content element, which must always exist at page load, and filter to only show tooltips when mousing over a span. The filtering happens "live" so will also work on newly injected spans.

Here's the above example code with this fix applied:

$(document).ready(function() {
  $(".content").tooltip({
      selector: 'span'
  });

  $('button').on('click', function() {
    $('.modal-body').html('<p>This <span title="Added after page load, tooltip now works!">Span2</span> was added after page load, the selector option makes sure it will work.</p>');
  });
});
span {
  color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css">

<div >
  <p>This span exists at page load and its tooltip works:
    <span title="Yes it works">Span1</span>
  </p>

  <p>Click the button below to add some HTML here after page load.</p>
  <div ></div>
</div>

<button>Add some HTML after page load</button>

Another less elegant option is to simply re-initialise .tooltip() on the new content, every time you load new content. This works but doesn't seem like a great approach. Here's our example code again with this option:

$(document).ready(function() {
  $(".content span").tooltip();

  $('button').on('click', function() {
    $('.modal-body').html('<p>This <span title="Added after page load">Span2</span> was added after page load, and we re-initialised tooltips to make it work.</p>');
    
    // After updating page content, re-initialise tooltips
    $(".content span").tooltip();
  });
});
span {
  color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css">

<div >
  <p>This span exists at page load and its tooltip works:
    <span title="Yes it works">Span1</span>
  </p>

  <p>Click the button below to add some HTML here after page load.</p>
  <div ></div>
</div>

<button>Add some HTML after page load</button>

jQuery is such an old and popular technology that IMO there are really no new jQuery questions here on SO, they've all been asked before :-) While this is no exception, there don't seem to be many great answers. Here are a few related questions I came across:

  • Related