Chargez un contenu popover Bootstrap avec AJAX. Est-ce possible?

90

Les éléments appropriés de ce que j'ai essayé sont ici:

<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?

CambridgeMike
la source
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
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: stackoverflow.com/a/39028723/1371408
Matty J

Réponses:

105

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.

Çağatay Gürtürk
la source
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
1
This workes, but the popover also stick for me, even though the unbind is before the get
Androme
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: '<iframe src="http://www.google.com"></iframe>'. 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
1
@FrzKhan you can use the e.off('hover') method
codenamev
3
this doesn't work due to stackoverflow.com/questions/4111194/… changing to .hover(function(){}) works.
arisalexis
132

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
la source
1
Genius answer! and thats why edited it to make it more readable
itsazzad
2
Great solution. With the current version of bootstrap however it seems that der might be some issue to this method 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
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
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
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
23

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
la source
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
It may be simpler, but it's also less elegant than the solution posted by @Ivan Klass.
Ian Kemp
6
async: false kills this for me
mxmissile
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
1
Synchronous AJAX is deprecated.
Barmar
9

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 Chzhen
la source
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
la source
For recent jquery : $('*[data-poload]').on('mouseenter mouseleave', function(event) {
jpprade
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
la source
7

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')
});
Dorian Margineanu
la source
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
la source
Same thing for me, the simplest & best one ;-)
Thomas Decaux
the problem with this is on every hover you are requesting data from the server. It should load the data only once.
Richard Torcato
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
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 stackoverflow.com/a/34030999/2524589
KSib
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
la source
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
la source
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
la source
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
la source
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
la source
1
<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");

});
Shankar Gupta
la source
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
la source
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
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
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
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
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: 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
1

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
la source
I was able to adapt this one easily to the solution I needed. Thank you!
Nieminen
0

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

E Steven
la source
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
la source
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
la source
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');
        });
    });
});
Mark Flavin
la source
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', {

            });
        });
    });
Warren Landis
la source
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
la source
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
la source
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.

Ho Thanh Binh
la source
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')
        }})
})
Thiago Bussiki
la source
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
la source