Matthew Renze
Matthew Renze

Reputation: 642

Data-driven Axis-Label Hyperlinks in D3

I'm trying to add data-driven hyperlinks to the y-axis labels for some D3.js charts that I'm creating. However, despite my best efforts to search online for a solution to this problem, I haven't yet found an exact solution (or I'm misunderstanding something in the solutions I've seen).

To keep things simple, I created a basic horizontal bar chart to use as an example. Here's the code:

    var table = [
          { id: 1, name: 'Entity 1', value: 10 },
          { id: 2, name: 'Entity 2', value: 20 },
          { id: 3, name: 'Entity 3', value: 30 },
        ];

    var height = 100;
    var width = 300;
    var leftMargin =  100;
    var rightMargin = 10;
    var topMargin = 10;
    var bottomMargin = 50;

    var x = d3.scale.linear()
        .domain([0, 30])
        .range([0, width]);

    var y = d3.scale.ordinal()
        .domain(table.map(function(d, i) {
            return d.name; }))
        .rangeRoundBands([0, height]);

    var chart = d3
        .select('body')
        .append('svg')
        .attr('height', height + topMargin + bottomMargin)
        .attr('width', width + leftMargin + rightMargin);

    var bars = chart
        .selectAll('rect')
        .data(table)
        .enter()
        .append('rect')
            .attr('x', x(0) + leftMargin)
            .attr('y', function(d, i) {
                return y(d.name) + topMargin; })
            .attr('height', y.rangeBand())
            .attr('width', function(d, i) {
                return x(d.value); });

    var xAxis = d3.svg
        .axis()
        .scale(x)
        .orient('bottom');

    chart
        .append('g')
        .attr("transform", "translate(" + leftMargin + "," + (height + 15) + ")")
        .call(xAxis);

    var yAxis = d3.svg
        .axis()
        .scale(y)
        .orient('left');

    chart
        .append('g')
        .attr("transform", "translate(" + (leftMargin - 5) + "," + topMargin + ")")
        .call(yAxis);

Here is the chart that this code produces (and yes, I've intentionally left it unstyled to keep things simple):

enter image description here

Essentially, what I need is for someone to demonstrate how to modify this code so that the y-axis labels are hyperlinks of the format "http://www.test.com/entity/{entityID}", where "{entityID"} is the integer ID associated with each row of the data".

I'm fine with either svg:a hyperlinks or a javascript on-click solution.

I've already looked at solutions that involve making the plot elements (e.g. the bars) hyperlinkable, but that solution doesn't solve this specific problem. In addition, I have multiple charts on the same page, so I'm not certain that a solution involving d3.selectAll('text') will work, unless there is a way to filter it to just the y-axis labels on a specific chart.

Any help you can provide would be greatly appreciated!

Upvotes: 3

Views: 224

Answers (1)

viggity
viggity

Reputation: 15237

I feel like the selectAll is the way to go. If you don't want to select all text elements, just add a class to the text or one of the text containers.

chart
    .append('g')
    .attr("transform", "translate(" + (leftMargin - 5) + "," + topMargin + ")")
    .attr("class", "entityLink") //***THIS IS NEW***
    .call(yAxis);

//*** THIS IS NEW ***
d3.selectAll(".entityLink text")
  .on("click", function() { alert("hooray"); });

css

.entityLink text {
    fill: blue;
    cursor: pointer;
}

full example: https://jsfiddle.net/memrr22q/

You'll have to figure out how to get the right data into the click event, but seems fairly easy.

Upvotes: 2

Related Questions