【问题标题】:How to bind bootstrap popover on dynamic elements如何在动态元素上绑定引导弹出框
【发布时间】:2013-06-04 03:25:30
【问题描述】:

我在动态列表中使用 Twitter Bootstrap 的弹出框。列表项有一个按钮,当我单击该按钮时,它应该显示弹出框。当我在非动态上进行测试时,它工作正常。

这是我用于非动态列表的 JavaScript

$("button[rel=popover]").popover({ 
    placement : 'right',
    container : 'body',
    html : true,
    //content:" <div style='color:red'>This is your div content</div>"
    content: function() {
      return $('#popover-content').html();
    }

    })
    .click(function(e) {
        e.preventDefault();
});

但是,它不适用于动态列表。当我单击“两次”按钮时它会显示出来,并且只显示我第一次单击的列表项之一。

我的html:

 <ul id="project-list" class="nav nav-list">
   <li class='project-name'>
     <a >project name 1
         <button class="pop-function" rel="popover" ></button>
     </a>
   </li>
   <li class='project-name'>
     <a>project name 2
        <button class="pop-function" rel="popover" ></button>
     </a>
   </li>

 </ul>

<div id="popover-content" style="display:none">
    <button class="pop-sync"></button>
    <button class="pop-delete"></button>
</div>

我的动态 JavaScript:

$(document).on("click", "#project-list li" , function(){
   var username = $.cookie("username");
   var projectName = $(this).text()
   $("li.active").removeClass("active");
   $(this).addClass("active");
   console.log("username: " +username + " project name: "+projectName );
});


$(document).on("click", "button[rel=popover]", function(){
    $(this).popover({ 
       placement : 'right',
       container : 'body',
       html : true,
    content: function() {
       return $('#popover-content').html();
        }

    }).click(function(e){
    e.preventDefault();
    })

});


//for close other popover when one popover button click
$(document).on("click", "button[rel=popover]" , function(){

        $("button[rel=popover]").not(this).popover('hide');
 });

我已经搜索了类似的问题,但我仍然找不到解决我的问题的问题。如果有人有一些想法,请告诉我。谢谢你的帮助。

【问题讨论】:

标签: javascript jquery twitter-bootstrap dom bootstrap-popover


【解决方案1】:

更新

如果您的弹出框将有一个一致的选择器,那么您可以使用弹出框构造函数的selector 属性。

var popOverSettings = {
    placement: 'bottom',
    container: 'body',
    html: true,
    selector: '[rel="popover"]', //Sepcify the selector here
    content: function () {
        return $('#popover-content').html();
    }
}

$('body').popover(popOverSettings);

Demo

其他方式:

  1. 标准方式)再次将弹出框绑定到正在插入的新项目。将 popoversettings 保存在外部变量中。
  2. 使用Mutation Event/Mutation Observer 来识别是否已将特定元素插入到ul 或元素中。

来源

var popOverSettings = { //Save the setting for later use as well
    placement: 'bottom',
    container: 'body',
    html: true,
    //content:" <div style='color:red'>This is your div content</div>"
    content: function () {
        return $('#popover-content').html();
    }

}

$('ul').on('DOMNodeInserted', function () { //listed for new items inserted onto ul
    $(event.target).popover(popOverSettings);
});

$("button[rel=popover]").popover(popOverSettings);
$('.pop-Add').click(function () {
    $('ul').append("<li class='project-name'>     <a>project name 2        <button class='pop-function' rel='popover'></button>     </a>   </li>");
});

但不建议使用DOMNodeInserted Mutation Event 来解决性能问题以及支持。这也是deprecated。因此,您最好的选择是在使用新元素更新后保存设置并绑定。

Demo

根据 MDN,另一种推荐的方法是使用 MutationObserver 而不是 MutationEvent,但在某些浏览器中的支持是未知的,性能问题。

MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
// create an observer instance
var observer = new MutationObserver(function (mutations) {
    mutations.forEach(function (mutation) {
        $(mutation.addedNodes).popover(popOverSettings);
    });
});

// configuration of the observer:
var config = {
     attributes: true, 
     childList: true, 
     characterData: true
};

// pass in the target node, as well as the observer options
observer.observe($('ul')[0], config);

Demo

【讨论】:

  • 嗨 PSL 感谢您的帮助。我真的不明白 MutationObserver。我厌倦了在演示中使用您的代码。当我单击动态列表时它工作正常,但问题是单击按钮时应该显示弹出框,而不是在 li 上。在演示中,第一个和第二个 lis 和按钮工作正常。请告诉我如何更改代码时单击 li 按钮并在第三个 li 之后出现弹出窗口。谢谢你的帮助。
  • @user2150267 如果你想要它在按钮上,你可以做$(event.target).find('button[rel=popover]').popover(popOverSettings);。但我不确定你是如何添加新的 li 的,但试试这个。
  • @user2150267 如果这不起作用,请告诉我。但我建议您在不使用任何突变的情况下使用选项 1(通过我的答案中的链接阅读您会知道,我猜对旧版 IE 的支持可能是一个问题)。如果您可以在添加新元素的同时向我展示您在做什么,我可以为您提供更好的输入..
  • 感谢您的帮助,但当我单击按钮而不是 li 时,我仍然不知道如何处理弹出框。
  • @user2150267 检查我之前的评论小提琴
【解决方案2】:

可能为时已晚,但这是另一种选择:

 $('body').popover({
    selector: '[rel=popover]',
    trigger: 'hover',
    html: true,
    content: function () {
        return $(this).parents('.row').first().find('.metaContainer').html();
    }
});

【讨论】:

    【解决方案3】:

    我这样做了,它对我有用。 “内容”是placesContent 对象。不是html内容!

    var placesContent = $('#placescontent');
    $('#places').popover({
            trigger: "click",
            placement: "bottom",
            container: 'body',
            html : true,
            content : placesContent,
        });
    
    $('#places').on('shown.bs.popover', function(){
      $('#addPlaceBtn').on('click', addPlace);
    }
    

    <div id="placescontent"><div id="addPlaceBtn">Add</div></div>
    

    【讨论】:

      【解决方案4】:

      试试这个 HTML

      <a href="#" data-toggle="popover" data-popover-target="#popover-content-1">Do Popover 1</a>
      <a href="#" data-toggle="popover" data-popover-target="#popover-content-2">Do Popover</a>
      
      <div id="popover-content-1" style="display: none">Content 1</div>
      <div id="popover-content-2" style="display: none">Content 2</div>
      

      jQuery:

      $(function() {
        $('[data-toggle="popover"]').each(function(i, obj) {
          var popover_target = $(this).data('popover-target');
          $(this).popover({
              html: true,
              trigger: 'focus',
              placement: 'right',
              content: function(obj) {
                  return $(popover_target).html();
              }
          });
        });
      });
      

      【讨论】:

        【解决方案5】:

        这就是我编写代码的方式,以便它可以使用弹出功能处理动态创建的元素。使用此代码,您可以触发弹出框默认显示。

        HTML:

        <div rel="this-should-be-the-target">
        </div>
        

        JQuery:

        $(function() {
            var targetElement = 'rel="this-should-be-the-target"';
            initPopover(targetElement, "Test Popover Content");
        
            // use this line if you want it to show by default
            $(targetElement).popover('show');
            
            function initPopover(target, popOverContent) {
                $(target).each(function(i, obj) {
                    $(this).popover({
                        placement : 'auto',
                        trigger : 'hover',
                        "html": true,
                        content: popOverContent
                    });
                 });
             }
        });
        

        【讨论】:

          【解决方案6】:

          更新一下,对于使用 bootstrap 5 的人来说,一个没有 jquery 的答案是

          var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
          popoverTriggerList.map(function (popoverTriggerEl) {
              return new bootstrap.Popover(popoverTriggerEl, {
                  content: get_content
              })
          })
          

          get_content 函数应使用this(弹出框元素)来生成动态内容。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-07-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多