151

I am using twitter's bootstrap's popover here. Right now, when i scroll over the popover text a popover appears with just text from the <a>'s data-content attribute. I was wondering if there was anyway to put a <div> inside the popover. Potentially, I would like to use php and mysql in there, but if i could get a div to work i think i can figure out the rest. I tried setting data-content to a div ID, but it didnt work.

HTML:

<a class='danger' 
   data-placement='above' 
   rel='popover' 
   data-content='#PopupDiv' 
   href='#'>Click</a>
Rubens Mariuzzo
  • 28,358
  • 27
  • 121
  • 148
kirby
  • 3,981
  • 14
  • 41
  • 54

8 Answers8

308

First of all, if you want to use HTML inside the content you need to set the HTML option to true:

$('.danger').popover({ html : true});

Then you have two options to set the content for a Popover

  • Use the data-content attribute. This is the default option.
  • Use a custom JS function which returns the HTML content.

Using data-content: You need to escape the HTML content, something like this:

<a class='danger' data-placement='above' 
   data-content="&lt;div&gt;This is your div content&lt;/div&gt;" 
   title="Title" href='#'>Click</a>

You can either escape the HTML manually or use a function. I don't know about PHP but in Rails we use html_safe.

Using a JS function: If you do this, you have several options. The easiest I think is to put your div content hidden wherever you want and then write a function to pass its content to popover. Something like this:

$(document).ready(function(){
  $('.danger').popover({ 
    html : true,
    content: function() {
      return $('#popover_content_wrapper').html();
    }
  });
});

And then your HTML looks like this:

<a class='danger' data-placement='above' title="Popover Title" href='#'>Click</a>
<div id="popover_content_wrapper" style="display: none">
  <div>This is your div content</div>
</div>

PS: I've had some troubles when using popover and not setting the title attribute... so, remember to always set the title.

starball
  • 20,030
  • 7
  • 43
  • 238
jävi
  • 4,571
  • 1
  • 24
  • 32
  • 5
    FYI, bootstrap has a class called "hide" that sets display: none – Dom M. Apr 23 '13 at 19:48
  • 1
    Just a note, but this approach is dreadfully slow for IE7, presumably because the copy of the html involves a lot of DOM manipulation. It's not usable in IE7, in our experience, so you need to lash it up another way. – philw Apr 14 '14 at 13:47
  • If you find that you need some javascript function attached to a link that's inside your `popover_content_wrapper`, this solution will cause problems because it's being rendered to html (without your handlers). The solution then is to listen for the "inserted.bs.popover" event and re-attach your handler to the new element that's now in the DOM. – Ryan Shillington Sep 19 '17 at 16:14
42

Building on jävi's answer, this can be done without IDs or additional button attributes like this:

http://jsfiddle.net/isherwood/E5Ly5/

<button class="popper" data-toggle="popover">Pop me</button>
<div class="popper-content hide">My first popover content goes here.</div>

<button class="popper" data-toggle="popover">Pop me</button>
<div class="popper-content hide">My second popover content goes here.</div>

<button class="popper" data-toggle="popover">Pop me</button>
<div class="popper-content hide">My third popover content goes here.</div>

$('.popper').popover({
    container: 'body',
    html: true,
    content: function () {
        return $(this).next('.popper-content').html();
    }
});
isherwood
  • 58,414
  • 16
  • 114
  • 157
11

Another alternate method if you wish to just have look and feel of pop over. Following is the method. Offcourse this is a manual thing, but nicely workable :)

HTML - button

<button class="btn btn-info btn-small" style="margin-right:5px;" id="bg" data-placement='bottom' rel="tooltip" title="Background Image"><i class="icon-picture icon-white"></i></button>

HTML - popover

<div class="bgform popover fade bottom in">
            <div class="arrow"></div>
             ..... your code here .......
</div>

JS

$("#bg").click(function(){
        $('.bgform').slideToggle();
});
A Bright Worker
  • 1,298
  • 14
  • 21
  • This worked for me, although I had to hardwire the location of the popover, which is not great, e.g. using `style="top: 200px; left: 90px;` to the `bgform` div. Is there a way to call bootstrap's automatic placement code instead? Also, you can use fadeToggle() or just toggle() for different effects in the javascript. – Racing Tadpole Oct 31 '13 at 22:39
  • This is the only correct way. html() creates a copy, making it unworkable for data-binding purposes. There is also no event for hooking into pre-transition state, so you cannot bind to popover until it is visible. – Daryl Teo Jan 15 '15 at 01:27
11

Late to the party. Building off the other solutions. I needed a way to pass the target DIV as a variable. Here is what I did.

HTML for Popover source (added a data attribute data-pop that will hold value for destination DIV id/or class):

<div data-html="true" data-toggle="popover" data-pop="popper-content" class="popper">

HTML for Popover content (I am using bootstrap hide class):

<div id="popper-content" class="hide">Content goes here</div>

Script:

$('.popper').popover({
placement: popover_placement,
container: 'div.page-content',
html: true,
trigger: 'hover',
content: function () {
    var pop_dest = $(this).attr("data-pop");
    //console.log(plant);
    return $("#"+pop_dest).html();
}});
Nisse Engström
  • 4,738
  • 23
  • 27
  • 42
Roman K
  • 394
  • 4
  • 5
8

In addition to other replies. If you allow html in options you can pass jQuery object to content, and it will be appended to popover's content with all events and bindings. Here is the logic from source code:

  • if you pass a function it will be called to unwrap content data
  • if html is not allowed content data will be applied as text
  • if html allowed and content data is string it will be applied as html
  • otherwise content data will be appended to popover's content container
$("#popover-button").popover({
    content: $("#popover-content"),
    html: true,
    title: "Popover title"
});
Ghasem
  • 14,455
  • 21
  • 138
  • 171
Birbone
  • 83
  • 1
  • 4
6

All of these answers miss a very important aspect!

By using .html or innerHtml or outerHtml you are not actually using the referenced element. You are using a copy of the element's html. This has some serious draw backs.

  1. You can't use any ids because the ids will be duplicated.
  2. If you load the contents every time that the popover is shown you will lose all of the user's input.

What you want to do is load the object itself into the popover.

https://jsfiddle.net/shrewmouse/ex6tuzm2/4/

HTML:

<h1> Test </h1>

<div><button id="target">click me</button></div>

<!-- This will be the contents of our popover -->
<div class='_content' id='blah'>
<h1>Extra Stuff</h1>
<input type='number' placeholder='number'/>
</div>

JQuery:

$(document).ready(function() {

    // We don't want to see the popover contents until the user clicks the target.
    // If you don't hide 'blah' first it will be visible outside of the popover.
    //
    $('#blah').hide();

    // Initialize our popover
    //
    $('#target').popover({
        content: $('#blah'), // set the content to be the 'blah' div
        placement: 'bottom',
        html: true
    });
    // The popover contents will not be set until the popover is shown.  Since we don't 
    // want to see the popover when the page loads, we will show it then hide it.
    //
    $('#target').popover('show');
    $('#target').popover('hide');

    // Now that the popover's content is the 'blah' dive we can make it visisble again.
    //
    $('#blah').show();


});
shrewmouse
  • 5,338
  • 3
  • 38
  • 43
  • 1
    If I could upvote this 100 times I would. I chased my tail forever trying to figure out why calling $('#' + id).val() in the popup kept returning a blank string. It's because of the darn html making a copy of the div. – Ntellect13 Jul 31 '18 at 17:27
-2
here is an another example

<a   data-container = "body" data-toggle = "popover" data-placement = "left" 
    data-content = "&lt;img src='<?php echo baseImgUrl . $row1[2] ?>' width='250' height='100' &gt;&lt;div&gt;&lt;h3&gt; <?php echo $row1['1'] ?>&lt/h3&gt; &lt;p&gt; &lt;span&gt;<?php echo $countsss ?>videos &lt;/span&gt;
&lt;span&gt;<?php echo $countsss1 ?> followers&lt;/span&gt;
&lt;/p&gt;&lt;/div&gt;
<?php echo $row1['4'] ?>   &lt;hr&gt;&lt;div&gt;
&lt;span&gt; &lt;button type='button' class='btn btn-default pull-left green'&gt;Follow  &lt;/button&gt;  &lt;/span&gt; &lt;span&gt; &lt;button type='button' class='btn btn-default pull-left green'&gt; Go to channel page&lt;/button&gt;   &lt;/span&gt;&lt;span&gt; &lt;button type='button' class='btn btn-default pull-left green'&gt;Close  &lt;/button&gt;  &lt;/span&gt;

 &lt;/div&gt;">

<?php echo $row1['1'] ?>
  </a>
Dinesh Sarak
  • 17
  • 1
  • 2
-2

Why so complicated? just put this :

data-html='true'
Sulung Nugroho
  • 1,605
  • 19
  • 14