Los bits apropiados de lo que probé están aquí:
<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')
})
Cuando hago clic, veo que se realiza la solicitud, pero no completa la ventana emergente. Ni siquiera veo que se agregue HTML para el popover al DOM, pero eso podría ser un error.
¿Alguien ha probado esto?
jquery
twitter-bootstrap
CambridgeMike
fuente
fuente
'shown.bs.popover'
controlador: stackoverflow.com/a/39028723/1371408Respuestas:
Consulte la publicación de mi blog para conocer la solución de trabajo: 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'); }); });
fuente
html
propiedad del popover entrue
, luego establecer lacontent
propiedad en una etiqueta HTML iframe, comocontent: '<iframe src="http://www.google.com"></iframe>'
. También necesitará anular lamax-width
propiedad de su popover usando CSS, y lo más probable es que elimine el estilo del iframe usando CSS también.e.off('hover')
métodoFunciona bien para mi:
$('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>'; }
fuente
Después de leer todas estas soluciones, creo que la solución se vuelve mucho más simple si usa una llamada ajax sincrónica . Luego puede 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'); });
fuente
async: false
mata esto para míHe actualizado la respuesta más popular. Pero en caso de que mis cambios no sean aprobados, pongo aquí una respuesta por separado.
Las diferencias son:
Primero debemos agregar un atributo data-poload a los elementos a los que le gustaría agregar un pop encima. El contenido de este atributo debe ser la URL a cargar (absoluta o relativa):
<a href="#" data-poload="/test.php">HOVER ME</a>
Y en JavaScript, preferiblemente en un $ (documento) .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')
evita cargar datos más de una vez ypopover()
vincula un nuevo evento de desplazamiento. Si desea que los datos se actualicen en cada evento de desplazamiento, debe eliminar el off.Consulte el JSFiddle funcional del ejemplo.
fuente
Una variación del código de Çağatay Gürtürk, puede usar la función delegar en su lugar y forzar la ocultación del popover en 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'); } });
fuente
La solución de Çağatay Gürtürk es agradable, pero experimenté la misma rareza descrita por Luke The Obscure:
Cuando la carga de ajax dura demasiado (o los eventos del mouse son demasiado rápidos), tenemos un .popover ('mostrar') y no .popover ('ocultar') en un elemento dado, lo que hace que el popover permanezca abierto.
Preferí esta solución de precarga masiva, todos los contenidos de popover se cargan y los eventos se manejan mediante bootstrap como en los popovers normales (estáticos).
$('.popover-ajax').each(function(index){ var el=$(this); $.get(el.attr('data-load'),function(d){ el.popover({content: d}); }); });
fuente
EN 2015, esta es la mejor respuesta
$('.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') });
fuente
Otra solución:
$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'); });
La idea aquí es activar manualmente la visualización de PopOver con mouseenter & mouseleave eventos .
En mouseenter , si no hay un PopOver creado para su artículo ( si ($ (this) .data ('popover') == null) ), créelo. Lo interesante es que puede definir su propio contenido PopOver pasándolo como argumento ( plantilla ) a la función popover () . No olvide establecer el parámetro html en verdadero también.
Aquí solo creo una plantilla oculta llamada popovertemplate y la clono con JQuery. No olvide eliminar el atributo id una vez que lo clone, de lo contrario, terminará con identificadores duplicados en el DOM. También observe que style = "display: none" para ocultar la plantilla en la 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>
Después del paso de creación (o si ya se ha creado), simplemente muestra el popOver con $ (this) .popover ('show');
Luego, la llamada clásica del Ajax. Si tiene éxito, debe limpiar el contenido anterior de la ventana emergente antes de colocar nuevos datos frescos del servidor . ¿Cómo podemos obtener el contenido actual de popover? ¡Con el selector .popover.in ! La clase .in indica que el popover se muestra actualmente, ¡ese es el truco aquí!
Para terminar, en el evento mouseleave , simplemente oculte el popover.
fuente
Aquí está mi solución que también funciona bien con contenido cargado ajax.
/* * 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'; }
fuente
Si no es probable que cambie el contenido de la ventana emergente, tendría sentido recuperarlo solo una vez. Además, algunas de las soluciones aquí tienen el problema de que si se desplaza rápidamente sobre varias "vistas previas", obtendrá varias ventanas emergentes abiertas. Esta solución aborda ambas cosas.
$('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'); } }); } });
fuente
Creo que mi solución es más simple con la funcionalidad predeterminada.
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>
fuente
Probé la solución de Çağatay Gürtürk pero obtuve la misma rareza que Luke the Obscure. Luego probé la solución de Asa Kusuma. Esto funciona, pero creo que el Ajax lee cada vez que se muestra el popover. La llamada a desvincular ('hover') no tiene ningún efecto. Eso es porque el delegado está monitoreando eventos en una clase específica, pero esa clase no ha cambiado.
Aquí está mi solución, muy basada en la de Asa Kusuma. Cambios:
delegate
poron
para que coincida con las nuevas bibliotecas de JQuery.fuente
Probé algunas de las sugerencias aquí y me gustaría presentar la mía (que es un poco diferente). Espero que ayude a alguien. Quería mostrar la ventana emergente en el primer clic y ocultarla en el segundo clic (por supuesto, actualizando los datos cada vez). Usé una variable adicional
visable
para saber si el popover es visible o no. Aquí está mi 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); }); } });
¡Salud!
fuente
<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"); });
fuente
A continuación, se muestra una forma que aborda algunos problemas:
._popper.update()
, que recalcula la posición del 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"); }); });
fuente
popover._popper.update()
y asegúrese de quepopover
,_popper
yupdate
todos tienen los valores esperados. Ciertamente es posible que hayan cambiado.Hay demasiadas respuestas aquí, pero tampoco encontré ninguna de ellas como quería. Extendí la respuesta de Ivan Klass para que Bootstrap 4 sea apropiada y se almacene en caché de manera inteligente.
Tenga en cuenta que el fragmento no cargará la dirección remota debido a la política CORS de 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>
fuente
Se ha dado una respuesta similar a esta en este hilo: Configurar el contenido de datos y mostrar el popover : es una manera mucho mejor de hacer lo que espera lograr. De lo contrario, tendrá que usar la opción live: true en las opciones del método popover. Ojalá esto ayude
fuente
$("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() }); });
tenga en cuenta que utilicé la misma etiqueta href y la hice para que no cambie de página cuando se hace clic, esto es bueno para SEO y también si el usuario no tiene javascript.
fuente
Me gusta la solución de Çağatay, pero las ventanas emergentes no se escondían en el mouseout. Agregué esta funcionalidad adicional con esto:
// hides the popup $('*[data-poload]').bind('mouseout',function(){ var e=$(this); e.popover('hide'); });
fuente
Usé la solución original pero hice un par de cambios:
Primero, usé en
getJSON()
lugar deget()
porque estaba cargando un script json. A continuación, agregué el comportamiento de activación de hover para solucionar el problema del pop-over.$('*[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'); }); }); });
fuente
Agregué html: true, por lo que no muestra la salida html sin procesar, en caso de que desee formatear sus resultados. También puede agregar más 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', { }); }); });
fuente
Mostrar popover ajax en un elemento estático con el disparador de desplazamiento:
$('.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>
fuente
$('[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>'; }
¡El contenido de Ajax se carga una vez! ver
el.data('bs.popover').options.content = response;
fuente
Lo hice y funciona perfecto con ajax y cargando contenido emergente.
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 });
Puede consultarlo en http://kienthuchoidap.com . Vaya a esto y coloque el cursor sobre el nombre de usuario del usuario.
fuente
Para mí, funciona cambiar el contenido de datos antes de cargar 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') }}) })
fuente
Esto funciona para mí, este código corrige posibles problemas de alineación:
<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 si acaso, el punto final que estoy usando devuelve html (un parcial de rieles)
Tomé parte del código de aquí https://stackoverflow.com/a/13565154/3984542
fuente