As partes apropriadas do que tentei estão aqui:
<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')
})
Quando clico, vejo a solicitação ser feita, mas não preenche o popover. Eu nem mesmo vejo HTML para o popover ser adicionado ao DOM, mas pode ser firebug.
alguem ja tentou isso?
jquery
twitter-bootstrap
CambridgeMike
fonte
fonte
'shown.bs.popover'
manipulador: stackoverflow.com/a/39028723/1371408Respostas:
Veja minha postagem do blog para a solução de trabalho: https://medium.com/cagataygurturk/load-a-bootstrap-popover-content-with-ajax-8a95cd34f6a4
<a href="#" title="blabla" data-poload="/test.php">blabla</a>
$('*[data-poload]').hover(function() { var e=$(this); e.off('hover'); $.get(e.data('poload'),function(d) { e.popover({content: d}).popover('show'); }); });
fonte
html
propriedade do popover como etrue
, em seguida, definir acontent
propriedade como uma tag HTML iframe, comocontent: '<iframe src="http://www.google.com"></iframe>'
. Você também precisará substituir amax-width
propriedade de seu popover usando CSS e, provavelmente, remover o estilo do iframe usando CSS também.e.off('hover')
métodoFunciona bem para mim:
$('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>'; }
fonte
Depois de ler todas essas soluções, acho que a solução se torna muito mais simples se você usar uma chamada ajax síncrona . Você pode então usar algo como:
$('#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'); });
fonte
async: false
mata isso para mimEu atualizei a resposta mais popular. Mas caso minhas alterações não sejam aprovadas, coloco aqui uma resposta separada.
As diferenças são:
Primeiro devemos adicionar um atributo data-poload aos elementos que você gostaria de adicionar um pop-over. O conteúdo deste atributo deve ser o url a ser carregado (absoluto ou relativo):
<a href="#" data-poload="/test.php">HOVER ME</a>
E em JavaScript, preferencialmente em um $ (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')
impede o carregamento de dados mais de uma vez epopover()
vincula um novo evento de foco. Se você quiser que os dados sejam atualizados a cada evento de foco, você deve remover o off.Por favor, veja o JSFiddle de trabalho do exemplo.
fonte
Uma variação do código de Çağatay Gürtürk, você poderia usar a função delegar em vez disso e forçar a ocultação do popover ao pairar.
$('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'); } });
fonte
A solução de Çağatay Gürtürk é boa, mas eu experimentei a mesma estranheza descrita por Luke The Obscure:
Quando o carregamento do ajax dura muito (ou os eventos do mouse são muito rápidos), temos um .popover ('show') e nenhum .popover ('ocultar') em um determinado elemento, fazendo com que o popover permaneça aberto.
Eu preferi essa solução de pré-carregamento massivo, todos os conteúdos do popover são carregados e os eventos são tratados por bootstrap como em popovers normais (estáticos).
$('.popover-ajax').each(function(index){ var el=$(this); $.get(el.attr('data-load'),function(d){ el.popover({content: d}); }); });
fonte
EM 2015, esta é a melhor resposta
$('.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') });
fonte
Outra solução:
$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'); });
A idéia aqui é para acionar manualmente a exibição de Popover com mouseenter e MouseLeave eventos.
No mouseenter , se não houver PopOver criado para o seu item ( if ($ (this) .data ('popover') == null) ), crie-o. O que é interessante é que você pode definir seu próprio conteúdo PopOver, passando-o como argumento ( modelo ) para a função popover () . Não se esqueça de definir o parâmetro html como verdadeiro também.
Aqui, acabei de criar um modelo oculto chamado popovertemplate e cloná-lo com JQuery. Não se esqueça de excluir o atributo id depois de cloná-lo, caso contrário, você acabará com ids duplicados no DOM. Observe também que style = "display: none" para ocultar o modelo na página.
<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>
Após a etapa de criação (ou se já tiver sido criada), você apenas exibe o popOver com $ (this) .popover ('show');
Em seguida, chamada de Ajax clássico. Em caso de sucesso, você precisa limpar o conteúdo antigo do popover antes de colocar novos dados novos do servidor . Como podemos obter o conteúdo popover atual? Com o seletor .popover.in ! A classe .in indica que o popover está sendo exibido no momento, esse é o truque aqui!
Para finalizar, no evento mouseleave , basta ocultar o popover.
fonte
Aqui está minha solução que funciona bem com conteúdo carregado em Ajax também.
/* * 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'; }
fonte
Se o conteúdo do popover não for alterado, faria sentido recuperá-lo apenas uma vez. Além disso, algumas das soluções aqui apresentam o problema de que, se você mover várias "visualizações" rapidamente, obterá vários pop-ups abertos. Esta solução aborda essas duas coisas.
$('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'); } }); } });
fonte
Acho que minha solução é mais simples com a funcionalidade padrão.
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>
fonte
Há muitas respostas aqui, mas também não achei nenhuma delas o que eu queria. Eu estendi a resposta de Ivan Klass para ser apropriado ao Bootstrap 4 e inteligentemente armazenado em cache.
Observe que o snippet não carregará realmente o endereço remoto devido à política CORS do Stackoverflow.
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>
fonte
uma resposta semelhante a esta foi dada neste tópico: Configurando o conteúdo dos dados e exibindo o popover - é uma maneira melhor de fazer o que você espera alcançar. Caso contrário, você terá que usar a opção live: true nas opções do método popover. Espero que isso ajude
fonte
Tentei a solução de Çağatay Gürtürk, mas obtive a mesma esquisitice de Luke, o Obscuro. Em seguida, tentei a solução de Asa Kusuma. Isso funciona, mas acredito que o Ajax lê todos o popover é exibido. A chamada para desvincular ('pairar') não tem efeito. Isso ocorre porque o delegado está monitorando eventos em uma classe específica - mas essa classe permanece inalterada.
Aqui está minha solução, estritamente baseada na de Asa Kusuma. Alterar:
delegate
poron
para corresponder às novas bibliotecas JQuery.fonte
Experimentei algumas das sugestões aqui apresentadas e gostaria de apresentar a minha (que é um pouco diferente) - espero que ajude alguém. Eu queria mostrar o pop-up no primeiro clique e ocultá-lo no segundo clique (é claro, atualizando os dados a cada vez). Usei uma variável extra
visable
para saber se o popover é visível ou não. Aqui está o meu código: 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); }); } });
Felicidades!
fonte
<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"); });
fonte
Esta é uma maneira que aborda alguns problemas:
._popper.update()
, que recalcula a posição do popover.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"); }); });
fonte
popover._popper.update()
e certifique-se de quepopover
,_popper
eupdate
todos têm os valores esperados. É certamente possível que aqueles tenham mudado.$("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 que usei a mesma tag href e fiz com que ela não mudasse de página quando clicada, isso é uma coisa boa para SEO e também se o usuário não tiver javascript!
fonte
Eu gosto da solução de Çağatay, mas os pop-ups não estavam se escondendo no mouseout. Eu adicionei esta funcionalidade extra com este:
// hides the popup $('*[data-poload]').bind('mouseout',function(){ var e=$(this); e.popover('hide'); });
fonte
Usei a solução original, mas fiz algumas alterações:
Primeiro, usei em
getJSON()
vez deget()
porque estava carregando um script json. Em seguida, adicionei o comportamento de gatilho de foco para corrigir o problema de pop-up pegajoso.$('*[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'); }); }); });
fonte
Eu adicionei html: true, então ele não mostra a saída html bruta, caso você queira formatar seus resultados. Você também pode adicionar mais controles.
$('*[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', { }); }); });
fonte
Exibir popover ajax no elemento estático com gatilho de foco:
$('.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>
fonte
$('[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>'; }
O conteúdo Ajax é carregado uma vez! Vejo
el.data('bs.popover').options.content = response;
fonte
Eu fiz e funcionou perfeitamente com ajax e carregamento de conteúdo popover.
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 });
Você pode conferir http://kienthuchoidap.com . Vá para isso e passe o mouse até o nome de usuário do usuário.
fonte
Para mim, o trabalho muda o conteúdo dos dados antes de carregar o 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') }}) })
fonte
Isso funciona para mim, este código corrige possíveis problemas de alinhamento:
<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'); } }); } });
Por precaução, o endpoint que estou usando retorna html (um parcial do rails)
Peguei parte do código daqui https://stackoverflow.com/a/13565154/3984542
fonte