How do I make Bootstrap popover work with HTML content in a seperate element

22,928

Solution 1

Any text/HTML you want to display in the popover can be added in a DIV which has a display:none; CSS property to it. You can pass a function to the content property of the popover options which gets the content from the hidden DIV. This way one doesn't need to reference by ID and insert script tags.

Here is an example http://jsfiddle.net/wb3n8/

HTML:

<div class="container">
    <div class="panel panel-default">
        <div class="panel-heading">
             <h3 class="panel-title">Panel title 1</h3>

        </div>
        <div class="panel-body">Panel content 1</div>
        <div class="my-popover-content">Here is some hidden content 1</div>
    </div>
    <div class="panel panel-default">
        <div class="panel-heading">
             <h3 class="panel-title">Panel title 2</h3>

        </div>
        <div class="panel-body">Panel content 2</div>
        <div class="my-popover-content">Here is some hidden content 2</div>
    </div>
    <div class="panel panel-default">
        <div class="panel-heading">
             <h3 class="panel-title">Panel title 3</h3>

        </div>
        <div class="panel-body">Panel content 3</div>
        <div class="my-popover-content">Here is some hidden content 3</div>
    </div>
</div>

CSS:

.my-popover-content {
    display:none;
}

Javascript:

$(document).ready(function () {
    popoverOptions = {
        content: function () {
            // Get the content from the hidden sibling.
            return $(this).siblings('.my-popover-content').html();
        },
        trigger: 'hover',
        animation: false,
        placement: 'bottom',
        html: true
    };
    $('.panel-heading').popover(popoverOptions);
});

Solution 2

An elegant solution is to place the HTML-content inside a script-tag with an id and then add a data-target="element_id_goes_here" attribute to the element that will trigger the popover. Since you're using popover you should already have some generic JavaScript somewhere that initializes the plugin. You can extend this JavaScript with a few lines of code.

HTML

<div class="panel panel-default">
    <div class="panel-heading">
        <i class="fa fa-briefcase fa-fw"></i> 
        <abbr title="Panel title" data-container="body" data-toggle="popover" 
              data-placement="bottom" data-trigger="hover" data-html="true" 
              data-target="#my-popover-content">
          Panel title
        </abbr>
        <div class="col-xs-6 col-md-4 pull-right" style="margin-top: -4px;">
            <!-- some buttons go here -->
        </div>
    </div>
    <!-- /.panel-heading -->
    </div>
    <!-- some panel content goes here -->
</div>

<script type="text/html" id="my-popover-content">
    *** HTML CONTENT GOES HERE ***
</script>

JavaScript

$("[data-toggle='popover']").each(function(index, element) {
    var contentElementId = $(element).data().target;
    var contentHtml = $(contentElementId).html();
    $(element).popover({
        content: contentHtml
    });
});

Solution 3

About Alexus1024 solution : I had to add a "#" before data.target in order to have jquery correctly selecting the target :

var contentElementId = "#"+data.target;

Solution 4

Solution, based on Martin Devillers post, but more flexible (passes all data-* tags into bootstrap js)

$("[data-toggle='popover']").each(function (index, element) {
    var data = $(element).data();
    if (data.target) {
        var contentElementId = data.target;
        var contentHtml = $(contentElementId).html();
        data.content = contentHtml;
    }
    $(element).popover(data);
});
Share:
22,928
Martin Devillers
Author by

Martin Devillers

Hi there! I’m a quirky extrovert software engineer with 15 years of professional software development experience, a life-long passion for technology, solving problems and helping people. The systems I’ve worked on are used by millions of people each day and have some meaningful impact on the world. MSc, BSc, Computer and Information Scientist with Latin Honors (Cum Laude)

Updated on February 15, 2020

Comments

  • Martin Devillers
    Martin Devillers over 4 years

    I am in the process of combining Bootstrap panels with Bootstrap popover functionality. The goal is to show a popover when the user hovers the panel's header. I've already got this to work, except that the data-content="" part becomes quite unmanageable when it has a lot of HTML inside.

    Below is some sample HTML I am working with. The part that says "LOADS OF HTML" contains div's, table's, p's, etc.

    <div class="panel panel-default">
        <div class="panel-heading">
            <i class="fa fa-briefcase fa-fw"></i> 
            <abbr title="Panel title" data-container="body" data-toggle="popover" 
                  data-placement="bottom" data-trigger="hover" data-html="true" 
                  data-content="<div>LOADS OF HTML HERE</div>">
              Panel title
            </abbr>
            <div class="col-xs-6 col-md-4 pull-right" style="margin-top: -4px;">
                <!-- some buttons go here -->
            </div>
        </div>
        <!-- /.panel-heading -->
        </div>
        <!-- some panel content goes here -->
    </div>
    

    Other Bootstrap plugins solve this issue by allowing you to put the HTML in a separate element and then reference that element with a "data-target" attribute. Unfortunately, Popover does not support this. How do I mimic this behavior without writing element specific JavaScript?