Загрузите содержимое Bootstrap popover с помощью AJAX. Это возможно?
соответствующие биты того, что я пробовал здесь:
<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')
})
когда я нажимаю, я вижу, что запрос сделан, но не заполняет popover. Я даже не вижу HTML для popover, добавленного в DOM, но это может быть firebug.
кто-нибудь пробовал это?
25 ответов:
см. мой пост в блоге для рабочего решения: https://medium.com/cagataygurturk/load-a-bootstrap-popover-content-with-ajax-8a95cd34f6a4
Сначала мы должны добавить атрибут data-poload к элементам, которые вы хотели бы хотелось бы добавить поп-музыки. Содержимое этого атрибута должно быть url для загрузки (абсолютный или относительный):
<a href="#" title="blabla" data-poload="/test.php">blabla</a>и в JavaScript, предпочтительно в a $(документ.)готов();
$('*[data-poload]').hover(function() { var e=$(this); e.off('hover'); $.get(e.data('poload'),function(d) { e.popover({content: d}).popover('show'); }); });
off('hover')предотвращает загрузку данных более одного раза иpopover()персонализация новое событие наведения. Если вы хотите, чтобы данные обновлялись при каждом наведении курсора случае, вы должны удалить выкл.пожалуйста, смотрите рабочий JSFiddle пример.
работает нормально для меня:
$('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>'; }
прочитав все эти решения, я думаю, что решение становится намного проще, если вы используете синхронно AJAX-вызов. Затем вы можете использовать что-то вроде:
$('#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'); });
вариант кода из Çağatay Gürtürk, вы можете использовать функцию делегата вместо этого и заставить скрывать popover на 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'); } });
другое решение:
$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'); });идея здесь заключается в том, чтобы вызвать вручную отображение PopOver с mouseenter & mouseleave событий.
On mouseenter, если нет Поповера, созданного для вашего элемента (если($(это).data ('popover') = = null)), создайте его. Интересно то, что вы можете определить свой собственный контент PopOver, передав его в качестве аргумента (шаблон) к popover () функция. Не забудьте установить html до правда также.
здесь я просто создаю скрытый шаблон под названием popovertemplate и клонировать его с помощью JQuery. не забудьте удалить атрибут id после его клонирования в противном случае вы будете в конечном итоге с дублированными идентификаторами в DOM. Также обратите внимание, что style= "display: none" чтобы скрыть шаблон на странице.
<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>после шага создания (или, если он уже создан), вы просто показываете popOver с $(этот).popover ('шоу');
затем классический вызов Ajax. На успех вам нужно очистите старое содержимое popover, прежде чем помещать новые свежие данные с сервера. Как мы можем получить текущий контент popover ? С помощью . popover.in селектор! Класс .in указывает, что popover в настоящее время отображается, вот в чем фокус!
до конца, по mouseleave событие, просто скрыть всплывающее окно.
решение Çağatay Gürtürk приятно, но я испытал ту же странность, описанную Люком неясным:
когда загрузка ajax длится слишком много (или события мыши слишком быстро) у нас есть .поповер ('шоу') и нет .popover ('hide') на данном элементе, заставляющем popover оставаться открытым.
Я предпочел это массовое решение для предварительной загрузки, все содержимое popover загружается, а события обрабатываются bootstrap, как в обычных (статических) popovers.
$('.popover-ajax').each(function(index){ var el=$(this); $.get(el.attr('data-load'),function(d){ el.popover({content: d}); }); });
в 2015 году, это лучший ответ!--2-->
$('.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') });
я обновил самый популярный ответ. Но в случае, если мои изменения не будут одобрены я ставлю здесь отдельный ответ.
отличия:
- загрузка текста отображается во время загрузки содержимого. Очень хорошо для медленного соединения.
- удалено мерцание, которое происходит, когда мышь покидает popover в первый раз.
Сначала мы должны добавить атрибут data-poload к элементам, которые вы хотели бы хотелось бы добавить поп-музыки. Содержание этого атрибут должен быть url для загрузки (абсолютный или относительный):
<a href="#" data-poload="/test.php">HOVER ME</a>и в JavaScript, предпочтительно в $(документ).готов();
// 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')предотвращает загрузку данных более одного раза иpopover()персонализация новое событие наведения. Если вы хотите, чтобы данные обновлялись при каждом наведении курсора случае, вы должны удалить выкл.пожалуйста, смотрите рабочий JSFiddle пример.
если содержимое в popover вряд ли изменится, имеет смысл получить его только один раз. Кроме того, в некоторых решениях здесь есть проблема, что если вы быстро перемещаете несколько "предварительных просмотров", вы получаете несколько открытых всплывающих окон. Это решение решает обе эти проблемы.
$('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'); } }); } });
Я думаю, что мое решение более простое с функциональностью по умолчанию.
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>
вот мое решение, которое отлично работает с загруженным контентом 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'; }
я попробовал решение Çağatay Gürtürk, но получил ту же странность, что и Люк неясный. Затем попробовал решение от Asa Kusuma. Это работает, но я считаю, что это делает Ajax читать время отображения всплывающего окна. Вызов unbind ('hover') не имеет никакого эффекта. Это потому, что делегат отслеживает события в определенном классе - но этот класс остается неизменным.
вот мое решение, тесно основанное на Asa Kusuma. Changes:
- заменить
delegateСonчтобы соответствовать новым библиотекам JQuery.- удалите класс 'withajaxpopover' вместо того, чтобы отменить привязку события наведения (которое никогда не было привязано)
- добавьте "trigger: hover" в popover, чтобы Bootstrap полностью обрабатывал его, начиная со второго использования.
- моя функция загрузки данных возвращает JSon, что позволяет легко указать как заголовок, так и содержимое для 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'); } }); });
я попробовал некоторые из предложений здесь, и я хотел бы представить мой (который немного отличается) - я надеюсь, что это поможет кому-то. Я хотел показать всплывающее окно при первом щелчке и скрыть его при втором щелчке (конечно с обновлением данных каждый раз). Я использовал дополнительную переменную
visableчтобы узнать, является ли popover видимым или нет. Вот мой код: 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); }); } });Ура!
<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"); });
ответ, подобный этому, был дан в этой теме: установка данных-содержание и отображение popover - это лучший способ сделать то, что вы надеетесь достичь. В противном случае вам придется использовать опцию live: true в параметрах метода popover. Надеюсь, это поможет
$("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() }); });обратите внимание, что я использовал тот же тег href и сделал это так, чтобы он не менял страницы при нажатии, это хорошо для SEO, а также если у пользователя нет javascript!
Мне нравится решение Çağatay, но я всплывающие окна не скрывались на mouseout. Я добавил эту дополнительную функциональность с этим:
// hides the popup $('*[data-poload]').bind('mouseout',function(){ var e=$(this); e.popover('hide'); });
я использовал исходное решение, но сделал несколько изменений:
во-первых, я использовал
getJSON()вместоget()потому что я загружал скрипт json. Затем я добавил поведение триггера наведения, чтобы исправить липкий поп над проблемой.$('*[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'); }); }); });
Я добавил html: true, поэтому он не показывает вывод raw html, если вы хотите отформатировать свои результаты. Вы также можете добавить дополнительные элементы управления.
$('*[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', { }); }); });
отображение ajax popover на статический элемент с наведением триггера:
$('.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>
$('[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 загружается один раз! смотрите
el.data('bs.popover').options.content = response;
Я сделал, и это прекрасно работает с ajax и загрузкой содержимого 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 });вы можете проверить это http://kienthuchoidap.com. перейдите к этому и наведите курсор на имя пользователя.
для меня работает изменение данных-содержание перед загрузкой 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') }}) })
это работает для меня, этот код исправить возможные проблемы выравнивания:
<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'); } }); } });на всякий случай, конечная точка, которую я использую, возвращает html (a rails partial)
Я взял часть кода отсюда https://stackoverflow.com/a/13565154/3984542
вот способ, который решает несколько вопросов:
- проблемы выравнивания после обновления контента, особенно если размещение "сверху". Ключом является вызов
._popper.update(), который пересчитывает положение popover.- изменение ширины после обновления содержимого. Он ничего не ломает, он просто выглядит раздражающим для пользователя. Чтобы уменьшить это, я установил ширину поповера на 100% (который затем закрывается
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"); }); });
Comments