robertjuh
robertjuh

Reputation: 311

Javascript tooltip cross browser incompatability

Greetings fellow coders!

I am working on a cool project in d3.js. Currently i am trying to make a tooltip work because in chrome it does not display the title attribute as a normal tooltip.

I found 2 solutions on the internet:

-Displaying the span of an element in a seperate box. I didn't seem to get this to work in my project.

-Using d3 to append a div to the svg so that a floating box of text appears next to the mouse. I managed to make this work, but only in chrome. If i do this in firefox, the box will appear in the bottom left. I even tried d3.mouse(this) for the coordinates but it just pops up at unexpected places.

In the fiddle, you can see both "solutions".

http://jsfiddle.net/fbba7u8h/5/

ps. firefox seemed to have trouble with the "event" thingy.

//square is defined in HTML, the red circle is made in js d3 code The javascript:

  d3.select("#square") 
    .on("mouseover", function(){return tooltip.style("visibility", "visible");})
    .on("mousemove", function(){return tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");})
    .on("mouseout", function(){return tooltip.style("visibility", "hidden");});

var tooltip = d3.select("body")
.append("div")
.attr("class", "halloTip")
.text("this is a tooltip using d3 js, in chrome it hovers next to mouse, in firefox it pops up in the bottom left! I also tried d3.mouse(this)[0] and [1] at the onMouseMove");

//the css style:

.halloTip{
    position:absolute;
    z-index:10;
    visibility:hidden;
    text:qqq;   
    background-color:rgb(5, 225, 153);
    stroke:black;   
    padding:11px;
}
.halloTip:hover{
    visibility:hidden;
    stroke-opacity:0.8; 
}

Upvotes: 2

Views: 224

Answers (2)

robjez
robjez

Reputation: 3788

Probably not a direct answer to your problem, but I wanted to show my implementation of tooltip on the graph, containing circles as data points.
My HTML is pretty simple and contains tooltip "holder" <div> container, and <section> element, which holds whole svg-graph, as so:

HTML:

<div id="tooltip" class="hidden">
  <p><span id="date"></span></p>
  <p><span id="value"></span></p>
</div>
<section class="graph"></section>   

Then in my javascript file, a among the other code I draw circles, with 3 event listeners:

JS:

var circles = svg.selectAll("circle")
            .data(newData)
            .enter()
            .append("circle")
            .attr(initialCircleAttrs)
            .on("mouseover", handleMouseOver)
            .on("mouseout", handleMouseOut);   

Now handleMouseOver and handleMouseOut are functions containing whole logic:

JS:

function handleMouseOut(d, i) {
        d3.select(this).attr({
            fill: "#fff",
            "stroke-width": 2,
            r: radius
        });

        //Hide the tooltip
        d3.select("#tooltip").classed("hidden", true);
    }

    function handleMouseOver(d, i) {
        d3.select(this).attr({
            fill: "#426426",
            "stroke-width": 0,
            r: radius * 2
        });

        // Tooltip
        //Get this bar's x/y values, then augment for the tooltip
        var xPosition = parseFloat(d3.select(this).attr("cx")) - 40;
        var yPosition = parseFloat(d3.select(this).attr("cy")) - 70;

        //Update the tooltip position and text
        d3.select("#tooltip")
            .style("left", xPosition + "px")
            .style("top", yPosition + "px")                 
            .select("#value")
            .text(parseFloat(d.Amount).toFixed(2));

        d3.select("#date")
            .text(dateFormat(parse(d.Date)));

        //Show the tooltip
        d3.select("#tooltip").classed("hidden", false);
    }   

handleMouseOver function changes the colour of the circle, then calculates x and y coordinates of data points, and based on that displays the #tooltip which has css attribute position set to absolute, as so:

CSS:

#tooltip {
    font-family:'Open Sans', Arial, sans-serif;
    font-size:14px;
    text-align:center;
    pointer-events: none;
    position: absolute;
    height: auto;
    padding: 10px;
    background-color: rgba(0,0,0,0.7);
    -webkit-border-radius: 3px;
    -moz-border-radius: 3px;
    border-radius: 3px;
    -webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.2);
    -moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
    box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
}

#tooltip.hidden {
    display: none;
}   

handleMouseOut function simply adds class hidden to the #tooltip.

This could potentially help in case of someone wanted to go with first approach you mentioned. It's a tooltip as a separate container toggled on mouseover and mouseout event.
I should also add, that it works perfectly in all modern browsers but also IE.

Upvotes: 0

Sebastian Nette
Sebastian Nette

Reputation: 7822

Try refering to d3.event instead of event.

.on("mousemove", function(){ ... d3.event.pageY ... }

If this also doesn't work then try a workaround ... something like:

var mouse = { x: 0, y: 0 };
document.addEventListener("mousemove", function(e) {
    mouse.x = e.pageX;
    mouse.y = e.pageY;
});

And then refer to mouse.x/mouse.y in the other callbacks

Upvotes: 1

Related Questions