block by milroc 2975255

Tooltip as a d3 helper

Full Screen

index.html

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript" src="//mbostock.github.com/d3/d3.js"></script>
    <script type="text/javascript" src="./tooltip.js"></script>
</head>
<body>
    <div class="viz"></div>
    <script type="text/javascript">

    var sampleSVG = d3.select(".viz")
        .append("svg")
        .attr("width", 600)
        .attr("height", 100);    

    var data = [];

    for (var i = 0; i < 100; i++) data.push(i);


    sampleSVG.selectAll("circle")
        .data(data)
        .enter().append("circle")
        .style("stroke", "gray")
        .style("fill", "aliceblue")
        .attr("r", 40)
        .attr("cx", function(d, i){return i*100 + 50;})
        .attr("cy", 50)
        .call(d3.helper.tooltip()
                .attr("class", function(d, i) { return d + " " +  i + " A"; })
                .attr("d", "b")
                .text(function(d, i){return "value: "+d;}));

    </script>
</body>
</html>

tooltip.js

d3.helper = {};

d3.helper.tooltip = function(){
    var tooltipDiv;
    var bodyNode = d3.select('body').node();    
    var attrs = [];
    var text = "";
    var styles = [];

    function tooltip(selection) {

        selection.on("mouseover", function(d, i){
            var name, value;
            // Clean up lost tooltips
            d3.select('body').selectAll('div.tooltip').remove();
            // Append tooltip
            tooltipDiv = d3.select('body').append('div');
            for (var i in attrs) {
                var name = attrs[i][0];
                if (typeof attrs[i][1] === "function") {
                    value = attrs[i][1](d, i);
                } else value = attrs[i][1];
                if (name === "class") value += " tooltip";
                tooltipDiv.attr(name, value);
            }
            for (var i in styles) {
                name = styles[i][0];
                if (typeof attrs[i][1] === "function") {
                    value = styles[i][1](d, i);
                } else value = styles[i][1];
                tooltipDiv.style(name, value);
            }
            var absoluteMousePos = d3.mouse(bodyNode);
            tooltipDiv.style('left', (absoluteMousePos[0] + 10)+'px')
                .style('top', (absoluteMousePos[1] - 15)+'px')
                .style('position', 'absolute') 
                .style('z-index', 1001);
            // Add text using the accessor function
            var tooltipText = '';
            if (typeof text === "function") tooltipText = text(d, i);
            else if (typeof text != "undefined" || typeof text != null) tooltipText = text;
            // Crop text arbitrarily
            tooltipDiv.style('width', function(d, i){return (tooltipText.length > 80) ? '300px' : null;})
                .html(tooltipText);
        })
        .on('mousemove', function(d, i) {
            // Move tooltip
            var absoluteMousePos = d3.mouse(bodyNode);
            tooltipDiv.style('left', (absoluteMousePos[0] + 10)+'px')
                .style('top', (absoluteMousePos[1] - 15)+'px');
            var tooltipText = '';
            if (typeof text === "string") tooltipText = text;
            if (typeof text === "function") tooltipText = text(d, i);
            tooltipDiv.html(tooltipText);
        })
        .on("mouseout", function(d, i){
            // Remove tooltip
            tooltipDiv.remove();
        });

    }

    tooltip.attr = function(name, value) {
        attrs.push(arguments);
        return this;
    }

    tooltip.text = function(value) {
        text = value;
        return this;
    }

    tooltip.style = function(name, value) {
        styles.push(arguments);
        return this;
    }

    return tooltip;
};