Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't Twitter Bootstrap popover work with SVG elements?

I'm more of a C++ guy, but I am working on some web UI stuff at the moment. I can't seem to get a Bootstrap popover to show up on an SVG element.

Any ideas? The popover works on the normal div.

jsFiddle is here: http://jsfiddle.net/JjAht/

<!DOCTYPE html>
<html>
<head>
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.2.2/css/bootstrap.min.css" rel="stylesheet">
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.2.2/css/bootstrap-responsive.min.css" rel="stylesheet">

<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.2.2/bootstrap.min.js"></script>
</head>
<body>
<div>
    <svg width="100" height="100">
        <circle r="45" cx="50" cy="50" style="fill: red"/>
    </svg>
</div>

<div class="well">
    <p>
    Hover here for a popover.
    </p>
</div>

<script type="text/javascript">

    $(document).ready(function() {
        var numCircles = $("circle").length;
        console.log("numCircles = " + numCircles);

        $("circle").popover({trigger:'hover', placement:'bottom', title:'Title!', content:'Content'});

        $("circle").css({"stroke":"blue"});

        $(".well").popover({trigger:'hover', placement:'bottom', title:'Title!', content:'Content'});
    } );
</script>
</body>
</html>
like image 866
Jon Stewart Avatar asked Dec 19 '12 00:12

Jon Stewart


1 Answers

From that example it looks like you need to modify Bootstrap to get this to work.

Under bootstrap-tooltip.js replace:

$tip
    .detach()
    .css({ top: 0, left: 0, display: 'block' })
    .insertAfter(this.$element)

pos = this.getPosition(inside)

with

if($('#'+this.$element[0].id,$('svg')).length > 0){
        $tip
          .remove()
          .css({ top: 0, left: 0, display: 'block' })
          .prependTo(document.body)

        pos = $.extend({}, this.$element.offset(), {
          width: this.$element[0].getBoundingClientRect().width
          , height: this.$element[0].getBoundingClientRect().height
        })
   } else {
         $tip
             .detach()
             .css({ top: 0, left: 0, display: 'block' })
             .insertAfter(this.$element)

         pos = this.getPosition(inside)
    }

There were basically two problems 1) bootstrap was inserting the div for the tooltip/popover into the SVG where the browser ignores it and 2) the position information needs to be calculated from the SVG

I've submitted this as a pull request on Github https://github.com/twitter/bootstrap/pull/6521

Update: It looks like bootstrap 2.3.0+ will support this via a new container property for tooltips/popovers. When working with SVG, set the container to body. See comments here https://github.com/twitter/bootstrap/pull/6521

An example:

svg.selectAll(".node").each(
    function(d,i){
        $(this).popover({title:"title", content:"content", container:"body"});
        // and/or $(this).tooltip({title:"tooltip - title", container:"body"});
    });
like image 197
Kristofor Carle Avatar answered Sep 28 '22 08:09

Kristofor Carle