Загрузите загрузочный контент 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 к элементам, которые вы бы как добавить pop к. Содержание этого атрибута должно быть url для загрузки (абсолютный или относительный):

<a href="#" title="blabla" data-poload="/test.php">blabla</a>

и в JavaScript, предпочтительно в $(документ.)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() персонализация новое событие наведения. Если вы хотите, чтобы данные обновлялись при каждом наведении курсора случае, вы должны удалить выкл.

см. Рабочая 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, если нет PopOver, созданного для вашего элемента (if ($(this).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 ('show');

затем классический вызов Ajax. На успех вам нужно очистите старое содержимое popover перед вводом новых свежих данных с сервера. Как мы можем получить текущий контент popover ? С .поповер.в селектор! В класса показывает, что диалоговое окно отображается, что тут хитрость!

до конца, по mouseleave событие, просто скрыть popover.


решение Çağatay Gürtürk приятно, но я испытал ту же странность, описанную Люком неясным:

когда загрузка ajax длится слишком много (или события мыши слишком быстрые), у нас есть .popover ("шоу") и нет .popover ('скрыть') для данного элемента, вызывающего 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 к элементам, которые вы бы как добавить pop к. Содержание этого атрибут должен быть url для загрузки (абсолютный или относительный):

<a href="#" data-poload="/test.php">HOVER ME</a>

и в JavaScript, желательно в $(документ).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() персонализация новое событие наведения. Если вы хотите, чтобы данные обновлялись при каждом наведении курсора случае, вы должны удалить выкл.

см. Рабочая 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';
}

я попробовал решение Чагатая Гюртюрка, но получил ту же странность, что и Люк неясный. Затем попробовал решение Asa Kusuma. Это работает, но я считаю, что это делает Ajax read время отображения всплывающего окна. Вызов unbind ('hover') не имеет никакого эффекта. Это потому, что делегат отслеживает события в определенном классе , но этот класс не изменяется.

вот мое решение, тесно основанное на Asa Kusuma. Изменения:

  • заменить 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');
          }
      });
    });

я попробовал некоторые из предложений здесь, и я хотел бы представить мой (который немного отличается) - я надеюсь, что это поможет кому-то. Я хотел ... --4-->показать всплывающее окно при первом щелчке и скрыть его при втором щелчке (конечно с обновлением данных каждый раз). Я использовал дополнительную переменную 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', {

            });
        });
    });

дисплей Аякс пирог на статический элемент при наведении триггер:

$('.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. Goto это и наведите курсор на имя пользователя.


для меня работает изменение содержимого данных перед загрузкой 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 (частичный rails)

Я взял часть кода отсюда https://stackoverflow.com/a/13565154/3984542


вот способ, который решает несколько вопросов:

  1. проблемы выравнивания после обновления содержимого, особенно если размещение "сверху". Ключ вызывает ._popper.update(), который пересчитывает положение popover.
  2. изменение ширины после обновления содержимого. Он ничего не ломает, он просто выглядит раздражающим для пользователя. Чтобы уменьшить это, я установил ширину 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");
        });
});