3

I am adding a tooltip with the <br> tag of html. It is working fine in chrome but not on firefox.

My code:

var dot = svg.append("g")
      .attr("class", "dots")
      .selectAll(".dot")
      .data(interpolateData(1))
      .enter().append("circle")
      .attr("class", "dot")

  // Add a title.
  dot.append("title")
     .each(function() {


      var d = d3.select(this);
d3.select(this).select("title")
       .html(function(d,i) { return d.name + ": " + Math.round(Number(d.avg)) + " avg each month <br>" + d.name + ": Build of "  + Math.round(Number(d.Checkin)) + " hrs each month";});

The tooltip is supposed to be displayed in 2 lines.Its working fine in chrome but not in firefox.

user1251007
  • 15,891
  • 14
  • 50
  • 76
krishna_v
  • 1,501
  • 5
  • 30
  • 60

2 Answers2

5

The SVG <title> element is treated inconsistently between browsers, because of the fact that it has a similar function but different rules compared with the HTML title attribute. Browsers seem to selectively choose which HTML rules they apply to the SVG and how.

The SVG <title> element specs indicate:

  • The title is primarily for accessibility purposes.

  • Browsers may display the title as a tooltip.

  • The top-level title in a stand-alone SVG document must be displayed, however (usually in the title bar, same as an HTML <title> element).

  • The title may contain content from other namespaces, with proper XML namespace attributes, but there is no indication of how these should be rendered when creating tooltips.

  • Any content not in another namespace should presumably be subject to the general SVG whitespace-handling rules, which require newlines to be ignored.

The HTML title attribute specs indicate that:

  • The title represents additional "advisory information" about the element.

  • Browsers must make the title information available to users, preferably in a device-independent manner (although most only show it on hover).

  • Linebreaks within the attribute must be respected when displaying the tooltip.

  • No other markup is allowed (because it is an attribute, not HTML code).

But...

Browser makers re-use the code for displaying HTML tooltips to display the SVG tooltips, and so things get confusing.

Follow along with this fiddle (remembering that this applies to inline SVG in an HTML document): http://fiddle.jshell.net/5npxba9L/6/

  • Hard line breaks and extra whitespace within an SVG <title>:

    • are preserved in Chrome 36, Opera 24 and Firefox 31 (i.e., the HTML attribute rules are applied)

    • are ignored in IE 11 (i.e., the SVG whitespace rules are applied)

  • Markup <br/> elements within an SVG <title>:

    • are stripped from the tooltip in Firefox 31

    • are displayed as linebreaks in Chrome 36, Opera 24 and IE 11

    • are completely ignored in all browsers when XML namespace prefixes are used (this might work differently in an XHTML document)

  • Other markup elements within an SVG <title>, such as SVG <tspan> elements:

    • are stripped from the tooltip in Firefox 31 and IE 11

    • are displayed as plain text (i.e. angle brackets printed out) in Chrome and Opera

  • Hard line breaks and extra whitespace are preserved in HTML title attributes, and extra markup is rendered as plain text, in all browsers tested (correctly)

So, the completely hacky and not according to specs way to get a multi-line tooltip in inline SVG, is to use both <br/> tags (un-namespaced or with a change in the default namespace) and hard line breaks within your <title> element:

<svg>
    <circle cx="250" r="50">
        <title><span xmlns="http://www.w3.org/1999/xhtml">Title with <br/>
a line break</span></title>
    </circle>
</svg>

Works in current versions of Chrome, Opera, Firefox and IE (haven't tested in Safari or mobile), although the webkit-based browsers will create an extra blank line.

Be warned, however: you won't be able to create the above markup with the d3 selection.html() method in most browsers, because that function relies on the HTMLElement.innerHTML DOM property, which isn't defined on SVG elements. You'd need to create text nodes and a <br> element separately. The easiest approach is to use a dummy HTML element as a parent, use innerHTML property to create the mixed content, and then append that to the title element:

dot.enter().append("circle")
      .attr("class", "dot")
      .attr("r", "50")
      .attr("cx", function(d,i){return i*100 + 50;})
  .append("title")
  .append(function(d, i){
      //when the parameter to `append()` is a function
      //it will be run for each element in the active selection
      //(in this case, the title elements)
      //and must return the actual element node to append.

      var span = document.createElement("span");
      span.innerHTML = "This is element <br/>\n #" + i;
      //the \n will be converted in Javascript to a line break
      return span;
  });

http://fiddle.jshell.net/cLLsgdmk/

That's all mostly a curiosity. If you want a more reliable solution, follow Lars' answer for a link to how to create a <foreignObject> tooltip, or check out this Codepen demo for information about how to use Javascript to overlay an absolutely positioned <div> on top of your SVG.

AmeliaBR
  • 27,344
  • 6
  • 86
  • 119
  • Thanks AmeliaBR, this gives a good overview, and since I'm browser-detecting on server-generated SVG, making this work in both my targets (IE11 and FF), should be pretty easy, if a little hacky. – Dave Nov 02 '14 at 19:58
4

The <br> tag you're using doesn't have a meaning in SVG -- the fact that Chrome is interpreting it the way you want is in violation of the standard. To get multiline text in SVG, you have basically two options:

  • Use multiple text or tspan elements.
  • Use foreignObject to embed HTML and use e.g. <br> there.

Some more information and pointers in this question.

Edit: These options do not apply to the title element (thanks to AmeliaBR for pointing it out).

Community
  • 1
  • 1
Lars Kotthoff
  • 107,425
  • 16
  • 204
  • 204
  • i tried adding like this:dot.append("foreignObject") .attr("width", 480) .attr("height", 500) .append("xhtml:title") .style("font", "14px 'Helvetica'") .html("Tooltip"); However this is adding a new forgeinobject tag but the title is not getting displayed on the dots. – krishna_v May 13 '14 at 09:52
  • There's no `title` element in HTML, append a `body` instead. See e.g. [here](http://bl.ocks.org/mbostock/1424037). – Lars Kotthoff May 13 '14 at 09:53
  • I tried appending the body. This is how it looks for each circle: Tooltip
    ToolTip1
    however the tooltip is not getting displayed
    – krishna_v May 13 '14 at 10:01
  • You can't append content to `circle` elements. Append to a `g` element or the top-level SVG. – Lars Kotthoff May 13 '14 at 10:06
  • i tried the following but still not working dot.append("foreignObject") .each(function() { //var d = d3.select(this); dot.attr("width", 480) dot.attr("height", 500) dot.append("g") dot.style("font", "14px 'Helvetica'") dot.html("Tooltip
    ToolTip1");
    – krishna_v May 13 '14 at 10:11
  • According to the code above, `dot` is a selection of `circle` elements. Do not append `foreignObject` to `circle`. – Lars Kotthoff May 13 '14 at 10:21
  • so how should the tooltip be added? can i just add append("g")? could help me in how to add the break in the circle element – krishna_v May 13 '14 at 10:25
  • thanks lars. I have made the changes and now i can display the tooltip in seperate lines. – krishna_v May 13 '14 at 11:28
  • *Sidenote:* The [specs](http://www.w3.org/TR/SVG11/struct.html#DescriptionAndTitleElements) actually say that "Description and title elements can contain marked-up text from other namespaces" (with appropriate namespace declaration), but don't require browsers to reflect that in tooltip displays (displaying tooltips for title elements is optional as a whole). *Another sidenote:* this isn't part of the specs, but Firefox (31) treats the content of SVG `` elements as pre-formatted text, so you can force a linebreak just by putting it in the text content. – AmeliaBR Sep 05 '14 at 15:33
  • Oh, it gets more complicated than that ... I'm going to post a separate answer. – AmeliaBR Sep 05 '14 at 15:46
  • P.S. @LarsKotthoff: You should edit the answer to make it clear that the options for multi-line text which you give do not apply inside a `` element automatic tooltip. – AmeliaBR Sep 05 '14 at 17:17