Загрузите загрузочный контент Bootstrap с помощью 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.
Кто-нибудь пробовал это?
Ответы
Ответ 1
Смотрите мое сообщение в блоге для рабочего решения: 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, желательно в $(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')
предотвращает загрузку данных более одного раза, а popover()
- привязки новое событие hover. Если вы хотите, чтобы данные обновлялись при каждом зависании события, вы должны удалить off.
Обратитесь к рабочему JSFiddle примера.
Ответ 2
Работает нормально для меня:
$('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>';
}
Ответ 3
Прочитав все эти решения, я думаю, что решение становится намного проще, если вы используете синхронный вызов 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');
});
Ответ 4
Изменив код из Ç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');
}
});
Ответ 5
Другое решение:
$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.
В mouseenter, если для вашего элемента не создано PopOver (if ($ (this).data('popover')) > null)), создайте Это. Интересно, что вы можете определить свой собственный контент PopOver, передав его как аргумент ( template) в функцию popover(). Не забудьте установить параметр html в true.
Здесь я просто создаю скрытый шаблон с именем 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 с помощью $(this).popover('show');
Тогда классический вызов Ajax. При успешном выполнении вам нужно очистить старый popover-контент, прежде чем вводить новые свежие данные с сервера. Как мы можем получить текущее содержимое popover? С помощью селектора .popover.in! Класс .in указывает, что popover в настоящее время отображается, что трюк здесь!
Чтобы завершить событие mouseleave, просто скройте popover.
Ответ 6
Решение Чагатай Гюртюрка приятно, но я испытал ту же странность, о которой говорил Люк Неясный:
Когда ajax-загрузка длится слишком много (или события мыши слишком быстрые), у нас есть .popover('show') и нет .popover('hide') для данного элемента, заставляя popover оставаться открытым.
Я предпочел это решение с массивной догрузкой, загрузилось все содержимое popover и события обрабатываются бутстрапом, как в обычных (статических) popovers.
$('.popover-ajax').each(function(index){
var el=$(this);
$.get(el.attr('data-load'),function(d){
el.popover({content: d});
});
});
Ответ 7
В 2015 году это лучший ответ
$('.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')
});
Ответ 8
Если содержимое в 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');
}
});
}
});
Ответ 9
Я думаю, что мое решение проще с функциональностью по умолчанию.
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>
Ответ 10
Я обновил самый популярный ответ. Но если мои изменения не будут одобрены, я поставлю здесь отдельный ответ.
Отличия:
- Загруженный текст отображается во время загрузки контента. Очень хорошо для медленного соединения.
- Удалено мерцание, которое происходит, когда мышь уходит в первый раз.
Сначала мы должны добавить атрибут data-poload к элементам, которые вы бы
как добавить всплывающее окно. Содержание этого атрибута должно быть
url для загрузки (абсолютный или относительный):
<a href="#" data-poload="/test.php">HOVER ME</a>
И в JavaScript, желательно в $(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')
предотвращает загрузку данных более одного раза, а popover()
- привязки
новое событие hover. Если вы хотите, чтобы данные обновлялись при каждом зависании
события, вы должны удалить off.
См. рабочий JSFiddle примера.
Ответ 11
Вот мое решение, которое отлично работает с загруженным содержимым 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';
}
Ответ 12
Я попробовал решение Çağatay Gürtürk, но получил ту же странность, что и Люк Неясный. Затем попробовал решение Асы Кусумы. Это работает, но я считаю, что Ajax читается каждый раз, когда отображается popover. Вызов развязать ( "зависание" ) не имеет никакого эффекта. Это потому, что делегат отслеживает события в определенном классе, но этот класс не изменяется.
Здесь мое решение, тесно связанное с Асой Кусумой. Изменения:
- Заменен
delegate
на on
для соответствия новым библиотекам JQuery.
- Удалите класс 'withajaxpopover' вместо того, чтобы разворачивать событие hover (которое никогда не было связано)
- Добавьте "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');
}
});
});
Ответ 13
Я попробовал некоторые из предложений здесь, и я хотел бы представить свою (что немного отличается) - я надеюсь, что это поможет кому-то. Я хотел показать всплывающее окно с первого щелчка и скрыть его при втором щелчке (конечно, с обновлением данных каждый раз).
Я использовал дополнительную переменную 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);
});
}
});
Ура!
Ответ 14
<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");
});
Ответ 15
в этой теме был дан ответ, подобный этому: Настройка содержимого данных и отображение popover - это лучший способ сделать то, что вы надеетесь достичь, В противном случае вам придется использовать опцию live: true в параметрах метода popover. Надеюсь, это поможет
Ответ 16
$("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!
Ответ 17
Мне нравится решение Çağatay, но я всплывающие окна не скрывались от мыши. Я добавил эту дополнительную функциональность:
// hides the popup
$('*[data-poload]').bind('mouseout',function(){
var e=$(this);
e.popover('hide');
});
Ответ 18
Я использовал исходное решение, но сделал пару изменений:
Сначала я использовал getJSON()
вместо get()
, потому что загружал json script. Затем я добавил триггерное поведение зависания, чтобы исправить липкую проблему.
$('*[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');
});
});
});
Ответ 19
Я добавил html: true, поэтому он не отображает исходный вывод 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', {
});
});
});
Ответ 20
Показать 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>
Ответ 21
$('[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;
Ответ 22
Я сделал, и он отлично работает с 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 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. Перейдите к этому и наведите указатель мыши на имя пользователя.
Ответ 23
Для меня работы меняют данные-содержимое перед загрузкой:
$('.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')
}})
})
Ответ 24
Это работает для меня, это исправление кода позволяет решить проблемы с выравниванием:
<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 (частичный рельс)
Я взял часть кода здесь fooobar.com/info/70607/...