92

The appropriate bits of what I tried are here:

<a href="#" data-content="<div id='my_popover'></div>"> Click here </a>

$(".button").popover({html: true})

$(".button").click(function(){
    $(this).popover('show');
    $("#my_popover").load('my_stuff')
})

When I click, I see the request get made, but doesn't populate the popover. I don't even see HTML for the popover get added to the DOM, but that could be firebug.

Has anyone tried this?

Ian Kemp
  • 28,293
  • 19
  • 112
  • 138
CambridgeMike
  • 4,562
  • 1
  • 28
  • 37
  • 1
    I haven't worked with bootstrap, but I would imagine that it's possible the element doesn't exist when you're trying to add content to it, but that's a guess. Are you getting any javascript errors? – Seth Nov 15 '11 at 00:27
  • If you have multiple popovers and want to load *different* content for each popover, then this answer is very neat and allows you to retain a lot of the out of the box setup for popovers - all you need to do is store the ID of the popover on attributes of the link, and read them in the `'shown.bs.popover'` handler: https://stackoverflow.com/a/39028723/1371408 – Matty J Jun 17 '19 at 00:23

26 Answers26

141

Works ok for me:

$('a.popup-ajax').popover({
    "html": true,
    "content": function(){
        var div_id =  "tmp-id-" + $.now();
        return details_in_popup($(this).attr('href'), div_id);
    }
});

function details_in_popup(link, div_id){
    $.ajax({
        url: link,
        success: function(response){
            $('#'+div_id).html(response);
        }
    });
    return '<div id="'+ div_id +'">Loading...</div>';
}
Ivan Klass
  • 6,407
  • 3
  • 30
  • 28
  • 2
    Great solution. With the current version of bootstrap however it seems that der might be some issue to this method https://github.com/twbs/bootstrap/issues/12563 .I had the twice issue and the fast solution was to ensure a title in each popover. This also means that I actually never see the Loading text you are using. – Rasmus Christensen Sep 25 '14 at 13:01
  • Works, except i had to use data-link instead of href, when using href my browser would simply opens url in href in new window. – TinusSky Oct 08 '14 at 13:47
  • @TinusSky: which browser are you talking about ? – Zulu Oct 28 '14 at 13:02
  • @Zulu latest firefox at that time, not sure if i had a special case, but i just posted it in case someone else has the same problem. – TinusSky Oct 28 '14 at 15:30
  • 20
    Does this not cause alignment issues? When using this approach on 3.3.1 (and using Chrome), the popover aligns itself when "Loading..." is displayed, but as soon as the true content of my popover is loaded, the alignment doesn't adjust accordingly... – Matt Jan 16 '15 at 14:29
  • 5
    Nice solution. One downside of this solution is that the ajax call is made twice. The popover component is a tooltip which first checks for content using hasContent and then gets the content with setContent. – Liam Feb 10 '15 at 19:21
  • @Matt if your alignment is right or left and the height of your content is fixed then you can add `
    ` as needed after `Loading...` to match the content and bring the alignment back.
    – haventchecked Jul 02 '15 at 03:01
  • Anyone have a solution for the alignment issue if popover placement is top? – david_i_smith Feb 19 '16 at 23:36
  • @david_i_smith In case you haven't found an answer after 2 years, I added an answer that addresses alignment: https://stackoverflow.com/a/49903939/1202807 – Gabriel Luci Apr 18 '18 at 15:49
109

See my blog post for the working solution: https://medium.com/cagataygurturk/load-a-bootstrap-popover-content-with-ajax-8a95cd34f6a4

First we should add a data-poload attribute to the elements you would like to add a pop over to. The content of this attribute should be the url to be loaded (absolute or relative):

<a href="#" title="blabla" data-poload="/test.php">blabla</a>

And in JavaScript, preferably in a $(document).ready();

$('*[data-poload]').hover(function() {
    var e=$(this);
    e.off('hover');
    $.get(e.data('poload'),function(d) {
        e.popover({content: d}).popover('show');
    });
});

off('hover') prevents loading data more than once and popover() binds a new hover event. If you want the data to be refreshed at every hover event, you should remove the off.

Please see the working JSFiddle of the example.

Cagatay Gurturk
  • 7,186
  • 3
  • 34
  • 44
  • 4
    I got some weirdness when I moused over twice before the ajax call completed... My popvers would "stick" open. I solved it by moving the "el.unbind('hover')" to right before the $.get(). – Luke The Obscure Apr 09 '12 at 21:45
  • 1
    This workes, but the popover also stick for me, even though the unbind is before the get – Androme May 13 '13 at 21:43
  • Thank you. The e.unbind('hover'); was the solution to my problem. – 12Bo Feb 04 '14 at 05:14
  • 2
    If you're trying to load an external URL, you'll run into cross-domain access restrictions. To get around this, you can set the popover's `html` property to `true`, then set the `content` property to an iframe HTML tag, like `content: ''`. You'll also need to override the `max-width` property of your popover using CSS, and most likely remove the styling of the iframe using CSS as well. – Gavin Mar 09 '14 at 19:38
  • how do you use the same for jquery latest version by using the `.on` method/ – Frz Khan Sep 05 '14 at 10:26
  • 1
    @FrzKhan you can use the `e.off('hover')` method – codenamev Sep 10 '14 at 13:35
  • 4
    this doesn't work due to http://stackoverflow.com/questions/4111194/cannot-use-bind-to-bind-hover changing to .hover(function(){}) works. – arisalexis Dec 01 '14 at 13:35
  • 1
    i also had to use `.hover()` instead of `bind()`. Also, neither `e.unbind('hover')` nor `e.off('hover')` worked for me for mouseleave. instead I had to follow the `.hover( handlerIn, handlerOut )` format as described in the jquery docs [here](https://api.jquery.com/hover/). specifically, I added the following code to the end of my method: `, function() { var e = $( this ); e.popover( 'hide' ) }` – allenwlee Apr 02 '15 at 02:33
  • I updated the code with new methods and added a jsfiddle – Cagatay Gurturk Apr 09 '15 at 21:01
  • 1
    It's broken, doesn't hide on a first mouse out event, have to mouse out twice after it was initialized. – Maksim Vi. May 12 '15 at 00:57
  • 1
    A working example for Bootstrap2 based on @ÇağatayGürtürk solution to get a part of the remote content in popover content. Added the hover out handle to prevent the popover sticks. `// hover (in,out) handler for remote content $('.remotepreview').hover(function() { var e = $(this); var container = $(this).attr('data-rel'); // the container with content to show e.off('hover'); $.get(e.data('remotecontent'), function(data) { var content = $(data).find(container); e.popover({content: content}).popover('show'); }); }, function() { $(this).popover('hide'); });` – drillingman Sep 11 '15 at 06:05
  • i have changed code and added mousleave event as i want to close popover on mouse leave but do not close popover if cursor is in popover content area. – Yashrajsinh Jadeja Dec 03 '15 at 12:45
  • Hi @ÇağatayGürtürk very helpful answer, my question is how can I stay open popover when muse enter to popover? Thanks – fool-dev Nov 09 '16 at 09:36
24

Having read all these solutions, I think the solution becomes much simpler if you use a synchronous ajax call. You can then use something like:

  $('#signin').popover({
    html: true,
    trigger: 'manual',
    content: function() {
      return $.ajax({url: '/path/to/content',
                     dataType: 'html',
                     async: false}).responseText;
    }
  }).click(function(e) {
    $(this).popover('toggle');
  });
Confusion
  • 16,256
  • 8
  • 46
  • 71
  • 1
    This helped me out tons, as I was having an issue with the popover rendering in a certain position before the ajax returned the contents (causing it to load off the screen). Thanks sir! – Derek May 01 '14 at 13:22
  • It may be simpler, but it's also less elegant than the solution posted by @Ivan Klass. – Ian Kemp Feb 23 '15 at 07:45
  • 6
    `async: false` kills this for me – mxmissile Nov 01 '16 at 17:00
  • While certainly easier, JavaScript and synchronous code don't really play well together. Since JavaScript is single-threaded this will block any code from executing for as long as the request takes. – IluTov Feb 01 '19 at 09:42
  • 1
    Synchronous AJAX is deprecated. – Barmar Nov 20 '19 at 22:51
11

I have updated the most popular answer. But in case my changes will not be approved I put here a separate answer.

Differences are:

  • LOADING text shown while content is loading. Very good for slow connection.
  • Removed flickering which occures when mouse leaves popover first time.

First we should add a data-poload attribute to the elements you would like to add a pop over to. The content of this attribute should be the url to be loaded (absolute or relative):

<a href="#" data-poload="/test.php">HOVER ME</a>

And in JavaScript, preferably in a $(document).ready();

 // On first hover event we will make popover and then AJAX content into it.
$('[data-poload]').hover(
    function (event) {
        var el = $(this);

        // disable this event after first binding 
        el.off(event);

        // add initial popovers with LOADING text
        el.popover({
            content: "loading…", // maybe some loading animation like <img src='loading.gif />
            html: true,
            placement: "auto",
            container: 'body',
            trigger: 'hover'
        });

        // show this LOADING popover
        el.popover('show');

        // requesting data from unsing url from data-poload attribute
        $.get(el.data('poload'), function (d) {
            // set new content to popover
            el.data('bs.popover').options.content = d;

            // reshow popover with new content
            el.popover('show');
        });
    },
    // Without this handler popover flashes on first mouseout
    function() { }
);

off('hover') prevents loading data more than once and popover() binds a new hover event. If you want the data to be refreshed at every hover event, you should remove the off.

Please see the working JSFiddle of the example.

Alexander C
  • 3,597
  • 1
  • 23
  • 39
8

IN 2015, this is the best answer

$('.popup-ajax').mouseenter(function() {
   var i = this
   $.ajax({
      url: $(this).attr('data-link'), 
      dataType: "html", 
      cache:true, 
      success: function( data{
         $(i).popover({
            html:true,
            placement:'left',
            title:$(i).html(),
            content:data
         }).popover('show')
      }
   })
});

$('.popup-ajax').mouseout(function() {
  $('.popover:visible').popover('destroy')
});
allenwlee
  • 665
  • 6
  • 21
7

The solution of Çağatay Gürtürk is nice but I experienced the same weirdness described by Luke The Obscure:

When ajax loading lasts too much (or mouse events are too quick) we have a .popover('show') and no .popover('hide') on a given element causing the popover to remain open.

I preferred this massive-pre-load solution, all popover-contents are loaded and events are handled by bootstrap like in normal (static) popovers.

$('.popover-ajax').each(function(index){

    var el=$(this);

    $.get(el.attr('data-load'),function(d){
        el.popover({content: d});       
    });     

});
fustaki
  • 1,574
  • 1
  • 13
  • 20
7

A variation of the code from Çağatay Gürtürk, you could use the delegate function instead and force hiding the popover on hoverout.

$('body').delegate('.withajaxpopover','hover',function(event){
    if (event.type === 'mouseenter') {
        var el=$(this);
        $.get(el.attr('data-load'),function(d){
            el.unbind('hover').popover({content: d}).popover('show');
        });
    }  else {
        $(this).popover('hide');
    }
});
Asa Kusuma
  • 114
  • 1
  • 3
6

Another solution:

$target.find('.myPopOver').mouseenter(function()
{
    if($(this).data('popover') == null)
    {
        $(this).popover({
            animation: false,
            placement: 'right',
            trigger: 'manual',
            title: 'My Dynamic PopOver',
            html : true,
            template: $('#popoverTemplate').clone().attr('id','').html()
        });
    }
    $(this).popover('show');
    $.ajax({
        type: HTTP_GET,
        url: "/myURL"

        success: function(data)
        {
            //Clean the popover previous content
            $('.popover.in .popover-inner').empty();    

            //Fill in content with new AJAX data
            $('.popover.in .popover-inner').html(data);

        }
    });

});

$target.find('.myPopOver').mouseleave(function()
{
    $(this).popover('hide');
});

The idea here is to trigger manually the display of PopOver with mouseenter & mouseleave events.

On mouseenter, if there is no PopOver created for your item (if($(this).data('popover') == null)), create it. What is interesting is that you can define your own PopOver content by passing it as argument (template) to the popover() function. Do not forget to set the html parameter to true also.

Here I just create a hidden template called popovertemplate and clone it with JQuery. Do not forget to delete the id attribute once you clone it otherwise you'll end up with duplicated ids in the DOM. Also notice that style="display: none" to hide the template in the page.

<div id="popoverTemplateContainer" style="display: none">

    <div id="popoverTemplate">
        <div class="popover" >
            <div class="arrow"></div>
            <div class="popover-inner">
                //Custom data here
            </div>
        </div>
    </div>
</div>

After the creation step (or if it has been already created), you just display the popOver with $(this).popover('show');

Then classical Ajax call. On success you need to clean the old popover content before putting new fresh data from server. How can we get the current popover content ? With the .popover.in selector! The .in class indicates that the popover is currently displayed, that's the trick here!

To finish, on mouseleave event, just hide the popover.

doanduyhai
  • 8,712
  • 27
  • 26
  • Same thing for me, the simplest & best one ;-) – Thomas Decaux May 08 '12 at 19:02
  • the problem with this is on every hover you are requesting data from the server. It should load the data only once. – Richard Torcato Jun 17 '13 at 14:37
  • 2
    @Richard Torcato In one hand you're right. It should be pretty easy to put the result to a cache though. In another hand, maybe we DO want to hit the server to load fresh data on every hover. So it's up to you to implement caching – doanduyhai Jun 18 '13 at 19:55
  • I realize this is old now, but in case someone is looking at this, I can't imagine this working well as it is if you have multiple popovers and you scroll over each of them. Hover over A, request sent for A, Hover over B and stay hovered on it, request sent for B, response from B arrives, updates the popover for B, response for A arrives, *updates the popover for B* (since the success function will just clear anything with that class. Looking at this to supplement the above might help though https://stackoverflow.com/a/34030999/2524589 – KSib Oct 10 '17 at 18:13
4

There are way too many answers here but I also found none of them to be what I wanted. I've extended Ivan Klass's answer to be both Bootstrap 4 appropriate and intelligently cached.

Note that the snippet won't actually load the remote address due to Stackoverflow's CORS policy.

var popoverRemoteContents = function(element) {
  if ($(element).data('loaded') !== true) {
    var div_id = 'tmp-id-' + $.now();
    $.ajax({
      url: $(element).data('popover-remote'),
      success: function(response) {
        $('#' + div_id).html(response);
        $(element).attr("data-loaded", true);
        $(element).attr("data-content", response);
        return $(element).popover('update');
      }
    });
    return '<div id="' + div_id + '">Loading...</div>';
  } else {
    return $(element).data('content');
  }
};

$('[data-popover-remote]').popover({
  html: true,
  trigger: 'hover',
  content: function() {
    return popoverRemoteContents(this);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>

<span data-popover-remote="http://example.com/">Remote Popover test with caching</span>
Archonic
  • 5,207
  • 5
  • 39
  • 55
3

Here is my solution which works fine with ajax loaded content too.

/*
 * popover handler assigned document (or 'body') 
 * triggered on hover, show content from data-content or 
 * ajax loaded from url by using data-remotecontent attribute
 */
$(document).popover({
    selector: 'a.preview',
    placement: get_popover_placement,
    content: get_popover_content,
    html: true,
    trigger: 'hover'
});

function get_popover_content() {
    if ($(this).attr('data-remotecontent')) {
        // using remote content, url in $(this).attr('data-remotecontent')
        $(this).addClass("loading");
        var content = $.ajax({
            url: $(this).attr('data-remotecontent'),
            type: "GET",
            data: $(this).serialize(),
            dataType: "html",
            async: false,
            success: function() {
                // just get the response
            },
            error: function() {
                // nothing
            }
        }).responseText;
        var container = $(this).attr('data-rel');
        $(this).removeClass("loading");
        if (typeof container !== 'undefined') {
            // show a specific element such as "#mydetails"
            return $(content).find(container);
        }
        // show the whole page
        return content;
    }
    // show standard popover content
    return $(this).attr('data-content');
}

function get_popover_placement(pop, el) {
    if ($(el).attr('data-placement')) {
        return $(el).attr('data-placement');
    }
    // find out the best placement
    // ... cut ...
    return 'left';
}
drillingman
  • 249
  • 3
  • 6
3

If the content in the popover isn't likely to change, it would make sense to retrieve it only once. Also, some of the solutions here have the issue that if you move over multiple "previews" fast, you get multiple open popups. This solution addresses both those things.

$('body').on('mouseover', '.preview', function() 
{
    var e = $(this);
    if (e.data('title') == undefined)
    {
        // set the title, so we don't get here again.
        e.data('title', e.text());

        // set a loader image, so the user knows we're doing something
        e.data('content', '<img src="/images/ajax-loader.gif" />');
        e.popover({ html : true, trigger : 'hover'}).popover('show');

        // retrieve the real content for this popover, from location set in data-href
        $.get(e.data('href'), function(response)
        {
            // set the ajax-content as content for the popover
            e.data('content', response.html);

            // replace the popover
            e.popover('destroy').popover({ html : true, trigger : 'hover'});

            // check that we're still hovering over the preview, and if so show the popover
            if (e.is(':hover'))
            {
                e.popover('show');
            }
        });
    }
});
towr
  • 4,147
  • 3
  • 20
  • 30
3

I think my solution is more simple with default functionality.

http://jsfiddle.net/salt/wbpb0zoy/1/

$("a.popover-ajax").each(function(){
   $(this).popover({
   trigger:"focus",
   placement: function (context, source) {
                  var obj = $(source);
      $.get(obj.data("url"),function(d) {
                        $(context).html( d.titles[0].title)
                  }); 
   },
   html:true,
   content:"loading"
   });
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>


<ul class="list-group">
  <li class="list-group-item"><a href="#" data-url="https://tr.instela.com/api/v2/list?op=today" class="popover-ajax">Cras justo odio</a></li>
  <li class="list-group-item"><a href="#" data-url="https://tr.instela.com/api/v2/list?op=today" class="popover-ajax">Dapibus ac facilisis in</a></li>
  <li class="list-group-item"><a href="#" data-url="https://tr.instela.com/api/v2/list?op=today" class="popover-ajax">Morbi leo risus</a></li>
  <li class="list-group-item"><a href="#" data-url="https://tr.instela.com/api/v2/list?op=today" class="popover-ajax">Porta ac consectetur ac</a></li>
  <li class="list-group-item"><a href="#" data-url="https://tr.instela.com/api/v2/list?op=today" class="popover-ajax">Vestibulum at eros</a></li>
</ul>
Salt Hareket
  • 764
  • 7
  • 18
1

I tried the solution by Çağatay Gürtürk but got the same weirdness as Luke the Obscure. Then tried the solution by Asa Kusuma. This works, but I believe it does the Ajax read every time the popover is displayed. The call to unbind('hover') has no effect. That's because delegate is monitoring for events in a specific class -- but that class is unchanged.

Here's my solution, closely based on Asa Kusuma's. Changes:

  • Replaced delegate with on to match new JQuery libraries.
  • Remove 'withajaxpopover' class rather than unbinding hover event (which was never bound)
  • Add "trigger: hover" to the popover so that Bootstrap will handle it completely beginning with the second use.
  • My data loading function returns JSon, which makes it easy to specify both the title and the content for the popover.
    /*  Goal: Display a tooltip/popover where the content is fetched from the
              application the first time only.

        How:  Fetch the appropriate content and register the tooltip/popover the first time 
              the mouse enters a DOM element with class "withajaxpopover".  Remove the 
              class from the element so we don't do that the next time the mouse enters.
              However, that doesn't show the tooltip/popover for the first time
              (because the mouse is already entered when the tooltip is registered).
              So we have to show/hide it ourselves.
    */
    $(function() {
      $('body').on('hover', '.withajaxpopover', function(event){
          if (event.type === 'mouseenter') {
              var el=$(this);
              $.get(el.attr('data-load'),function(d){
                  el.removeClass('withajaxpopover')
                  el.popover({trigger: 'hover', 
                              title: d.title, 
                              content: d.content}).popover('show');
              });
          }  else {
              $(this).popover('hide');
          }
      });
    });
bwbecker
  • 1,031
  • 9
  • 21
1

I tried some of the suggestions here and I would like to present mine (which is a bit different) - I hope it will help someone. I wanted to show the popup on first click and hide it on second click (of course with updating the data each time). I used an extra variable visable to know whether the popover is visable or not. Here is my code: HTML:

<button type="button" id="votingTableButton" class="btn btn-info btn-xs" data-container="body" data-toggle="popover" data-placement="left" >Last Votes</button>

Javascript:

$('#votingTableButton').data("visible",false);

$('#votingTableButton').click(function() {  
if ($('#votingTableButton').data("visible")) {
    $('#votingTableButton').popover("hide");
    $('#votingTableButton').data("visible",false);          
}
else {
    $.get('votingTable.json', function(data) {
        var content = generateTableContent(data);
        $('#votingTableButton').popover('destroy');
        $('#votingTableButton').popover({title: 'Last Votes', 
                                content: content, 
                                trigger: 'manual',
                                html:true});
        $('#votingTableButton').popover("show");
        $('#votingTableButton').data("visible",true);   
    });
}   
});

Cheers!

ItayB
  • 10,377
  • 9
  • 50
  • 77
1

Here is a way that addresses a few issues:

  1. Alignment issues after content is updated, especially if the placement is "top". The key is calling ._popper.update(), which recalculates the position of the popover.
  2. Width change after the content is updated. It doesn't break anything, it just looks jarring to the user. To lessen that, I set the width of the popover to 100% (which is then capped by the max-width).
var e = $("#whatever");
e.popover({
    placement: "top",
    trigger: "hover",
    title: "Test Popover",
    content: "<span class='content'>Loading...</span>",
    html: true
}).on("inserted.bs.popover", function() {
    var popover = e.data('bs.popover');
    var tip = $(popover.tip);
    tip.css("width", "100%");
    $.ajax("/whatever")
        .done(function(data) {
            tip.find(".content").text(data);
            popover._popper.update();
        }).fail(function() {
            tip.find(".content").text("Sorry, something went wrong");
        });
});
Gabriel Luci
  • 38,328
  • 4
  • 55
  • 84
  • I like the concepts, but unfortunately they're not working for me... (namely the position update and 100% width) Not sure if these have changed with Bootstrap 4? – Ben in CA Oct 28 '19 at 20:58
  • The 100% width probably depends on how your elements are laid out... maybe. Is the box still widening after the content is loaded? – Gabriel Luci Oct 29 '19 at 02:40
  • For the position, you can set a breakpoint at `popover._popper.update()` and make sure that `popover`, `_popper` and `update` all have the expected values. It is certainly possible that those have changed. – Gabriel Luci Oct 29 '19 at 02:41
  • Right - the box widens after new content. And I tried writing some of the values to the console and was getting undefined. – Ben in CA Oct 29 '19 at 14:38
  • @BeninCA It still works for me. Here's a fiddle to demonstrate: https://jsfiddle.net/5pvx6z3g/1/ – Gabriel Luci Oct 29 '19 at 16:23
  • 1
    - You're right. Turns out I was trying to do some more complex stuff a the same time and then it wasn't working. But now I've been able to incorporate that too. Here's a fiddle: https://jsfiddle.net/udfz5wrv/1/ Enables you to use selectors (if you need to bind handlers, etc.), access data from the selector, display a bootstrap loading spinner, etc. – Ben in CA Oct 29 '19 at 22:07
1

an answer similar to this has been given in this thread: Setting data-content and displaying popover - it is a way better way of doing what you hope to achieve. Otherwise you will have to use the live: true option in the options of the popover method. Hopefully this helps

Community
  • 1
  • 1
E Steven
  • 81
  • 9
0

I like Çağatay's solution, but I the popups were not hiding on mouseout. I added this extra functionality with this:

// hides the popup
$('*[data-poload]').bind('mouseout',function(){
   var e=$(this);
   e.popover('hide'); 
});
Mino
  • 911
  • 1
  • 7
  • 14
0

I used the original solution but made a couple of changes:

First, I used getJSON() instead of get() because I was loading a json script. Next I added the trigger behaviour of hover to fix the sticky pop over issue.

$('*[data-poload]').on('mouseover',function() {
    var e=$(this);
    $.getJSON(e.data('poload'), function(data){
        var tip;
        $.each(data, function (index, value) {
           tip = this.tip;
           e.popover({content: tip, html: true, container: 'body', trigger: 'hover'}).popover('show');
        });
    });
});
cfi
  • 10,915
  • 8
  • 57
  • 103
0

I added html: true, so it doesn't show raw html output, in case you want to format your results. You can also add in more controls.

    $('*[data-poload]').bind('click',function() {
        var e=$(this);
        e.unbind('click');
        $.get(e.data('poload'),function(d) {
            e.popover({content: d, html: true}).popover('show', {

            });
        });
    });
0

Display ajax popover on static element with hover trigger:

$('.hover-ajax').popover({
    "html": true,
    trigger: 'hover',
    "content": function(){
        var div_id =  "tmp-id-" + $.now();
        return details_in_popup($(this).attr('href'), div_id);
    }
});

function details_in_popup(link, div_id){
    $.ajax({
        url: link,
        success: function(response){
            $('#'+div_id).html(response);
        }
    });
    return '<div id="'+ div_id +'">Loading...</div>';
}

Html :

<span class="hover-ajax" href="http://domain.tld/file.php"> Hey , hoover me ! </span>
Alin Razvan
  • 1,451
  • 13
  • 18
0
  $('[data-poload]').popover({
    content: function(){
      var div_id =  "tmp-id-" + $.now();
      return details_in_popup($(this).data('poload'), div_id, $(this));
    },
    delay: 500,

    trigger: 'hover',
    html:true
  });

  function details_in_popup(link, div_id, el){
      $.ajax({
          url: link,
          cache:true,
          success: function(response){
              $('#'+div_id).html(response);
              el.data('bs.popover').options.content = response;
          }
      });
      return '<div id="'+ div_id +'"><i class="fa fa-spinner fa-spin"></i></div>';
  }   

Ajax content is loaded once! see el.data('bs.popover').options.content = response;

SirCumz
  • 171
  • 1
  • 2
  • 14
0

I did and it's work perfect with ajax and loading on popover content.

var originalLeave = $.fn.popover.Constructor.prototype.leave;
        $.fn.popover.Constructor.prototype.leave = function(obj){
            var self = obj instanceof this.constructor ?
                obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
            var container, timeout;

            originalLeave.call(this, obj);

            if(obj.currentTarget) {
                container = $(obj.currentTarget).siblings('.popover')
                timeout = self.timeout;
                container.one('mouseenter', function(){
                    //We entered the actual popover – call off the dogs
                    clearTimeout(timeout);
                    //Let's monitor popover content instead
                    container.one('mouseleave', function(){
                        $.fn.popover.Constructor.prototype.leave.call(self, self);
                    });
                })
            }
        };
        var attr = 'tooltip-user-id';
        if ($('a['+ attr +']').length)
            $('a['+ attr +']').popover({
                html: true,
                trigger: 'click hover',
                placement: 'auto',
                content: function () {
                    var this_ = $(this);
                    var userId = $(this).attr(attr);
                    var idLoaded = 'tooltip-user-id-loaded-' + userId;
                    var $loaded = $('.' + idLoaded);
                    if (!$loaded.length) {
                        $('body').append('<div class="'+ idLoaded +'"></div>');
                    } else if ($loaded.html().length) {
                        return $loaded.html();
                    }
                    $.get('http://example.com', function(data) {
                        $loaded.html(data);
                        $('.popover .popover-content').html(data);
                        this_.popover('show');
                    });
                    return '<img src="' + base_url + 'assets/images/bg/loading.gif"/>';
                },
                delay: {show: 500, hide: 1000},
                animation: true
            });

You can check it out http://kienthuchoidap.com. Goto this and hover to username of user.

0
<button type="button" id="popover2" title="" data-content="<div id='my_popover' style='height:250px;width:300px;overflow:auto;'>Loading...Please Wait</div>" data-html="true" data-toggle="popover2" class="btn btn-primary" data-original-title="A Title">Tags</button>

$('#popover2').popover({ 
    html : true,
    title: null,
    trigger: "click",
    placement:"right"
});

$("#popover2").on('shown.bs.popover', function(){
    $('#my_popover').html("dynamic content loaded");

});
ADyson
  • 57,178
  • 14
  • 51
  • 63
0

For me works change data-content befora load popover:

$('.popup-ajax').data('content', function () {
    var element = this;
    $.ajax({
        url: url,
        success: function (data) {

            $(element).attr('data-content', data)

            $(element).popover({
                html: true,
                trigger: 'manual',
                placement: 'left'
            });
            $(element).popover('show')
        }})
})
0

This works for me, this code fix possibles alignment issues:

<a class="ajax-popover" data-container="body" data-content="Loading..." data-html="data-html" data-placement="bottom" data-title="Title" data-toggle="popover" data-trigger="focus" data-url="your_url" role="button" tabindex="0" data-original-title="" title="">
  <i class="fa fa-info-circle"></i>
</a>

$('.ajax-popover').click(function() {
  var e = $(this);
  if (e.data('loaded') !== true) {
    $.ajax({
      url: e.data('url'),
      dataType: 'html',
      success: function(data) {
        e.data('loaded', true);
        e.attr('data-content', data);
        var popover = e.data('bs.popover');
        popover.setContent();
        popover.$tip.addClass(popover.options.placement);
        var calculated_offset = popover.getCalculatedOffset(popover.options.placement, popover.getPosition(), popover.$tip[0].offsetWidth, popover.$tip[0].offsetHeight);
        popover.applyPlacement(calculated_offset, popover.options.placement);
      },
      error: function(jqXHR, textStatus, errorThrown) {
        return instance.content('Failed to load data');
      }
    });
  }
});

Just in case, the endpoint I'm using returns html (a rails partial)

I took some part of the code from here https://stackoverflow.com/a/13565154/3984542

vicente.fava
  • 360
  • 3
  • 14
0
$("a[rel=popover]").each(function(){
        var thisPopover=$(this);
                var thisPopoverContent ='';
                if('you want a data inside an html div tag') {
                thisPopoverContent = $(thisPopover.attr('data-content-id')).html();
                }elseif('you want ajax content') {
                    $.get(thisPopover.attr('href'),function(e){
                        thisPopoverContent = e;
                    });
            }
        $(this).attr(   'data-original-title',$(this).attr('title') );
        thisPopover.popover({
            content: thisPopoverContent
        })
        .click(function(e) {
            e.preventDefault()
        });

    });

note that I used the same href tag and made it so that it doesn't change pages when clicked, this is a good thing for SEO and also if user doesn't have javascript!

Neo
  • 11,078
  • 2
  • 68
  • 79