Cybernetic
Cybernetic

Reputation: 13334

Access a value in JSON when clicking a specific node in D3.js

I am using a pack layout in D3 as follows:

var margin = 20,
diameter = 500;

var color = d3.scale.linear()
//var color = ['steelblue','green','grey']
    //.domain([3, 4])
    .range(["steelblue", "#81CFE0", "darkslategrey"])
    .interpolate(d3.interpolateHcl);

var pack = d3.layout.pack()
    .padding(2)
    .size([diameter - margin, diameter - margin])
    .value(function(d) { return d.size; })

var svg = d3.select("body").append("svg")
    .attr("width", diameter)
    .attr("height", diameter)
    .append("g")
    .attr("transform", "translate(" + diameter / 2 + "," + diameter / 2 + ")");

d3.json("data.json", function(error, root) {
    if (error) throw error;

    var focus = root,
    nodes = pack.nodes(root),
    view;

    var circle = svg.selectAll("circle")
        .data(nodes)
        .enter().append("circle")
        .attr("class", function(d) { return d.parent ? d.children ? "node" : "node node--leaf" : "node node--root"; })
        .style("fill", function(d) { return d.children ? color(d.depth) : null; })
        .on("click", function(d) { if (focus !== d) zoom(d), d3.event.stopPropagation(); });

    var text = svg.selectAll("text")
        .data(nodes)
        .enter().append("text")
        .attr("class", "label")
        .style("fill", "black")
        .style("display", function(d) { return d.parent === root ? null : "none"; })
        .text(function(d) { return d.name; });

    var node = svg.selectAll("circle,text");

    d3.select("body")
        .data(nodes)
        .style("background", color(-1))

    zoomTo([root.x, root.y, root.r * 2 + margin]);

    function zoom(d) {
        var focus0 = focus; focus = d;

        var transition = d3.transition()
            .duration(d3.event.altKey ? 7500 : 750)
            .tween("zoom", function(d) {
                var i = d3.interpolateZoom(view, [focus.x, focus.y, focus.r * 2 + margin]);
                return function(t) { zoomTo(i(t)); };
            } );

        transition.selectAll("text")
            .filter(function(d) { return d.parent === focus || this.style.display === "inline"; })
            .style("fill", "darkslategrey")
            .each("start", function(d) { if (d.parent === focus) this.style.display = "inline"; })
            .each("end", function(d) { if (d.parent !== focus) this.style.display = "none"; });
    }

    function zoomTo(v) {
        var k = diameter / v[2]; view = v;
        node.attr("transform", function(d) { return "translate(" + (d.x - v[0]) * k + "," + (d.y - v[1]) * k + ")"; });
        circle.attr("r", function(d) { return d.r * k; });
    }
}); 
d3.select(self.frameElement).style("height", diameter + "px");

Currently, if a node--leaf is clicked, it just zooms back out. But I want to instead alert the URL stored in the JSON for that node.

JSON looks like this:

{
    "name": "Packages",
    "children": [
        {
            "name": "Talks",
            "children": [
                {
                    "name": "talk_1",
                    "size": 722,
                    "url": "www.example_1.com"
                },
                {
                    "name": "talk_2",
                    "size": 722,
                    "url": "www.example_2.com"
                },
                {
                    "name": "talk_3",
                    "size": 722,
                    "url": "www.example_3.com"
                }
            ]
        }
    ]
}

So if I click on the talk_3 node, I should get www.example_3.com by accessing d.url.

Upvotes: 0

Views: 429

Answers (2)

Cyril Cherian
Cyril Cherian

Reputation: 32327

You can get the access to the URL in the click function as shown below:

var circle = svg.selectAll("circle")
            .data(nodes)
            .enter().append("circle")
            .attr("class", function (d) {
            return d.parent ? d.children ? "node" : "node node--leaf" : "node node--root";
        })
            .style("fill", function (d) {
            return d.children ? color(d.depth) : null;
        })
            .on("click", function (d) {
              var win = window.open(d.url, '_blank');
              win.focus();
             console.log(d.url);
            if (focus !== d) zoom(d), d3.event.stopPropagation();
        });

In the click function this will open up the URL in the new tab:

var win = window.open(d.url, '_blank');
win.focus();

Upvotes: 1

somename
somename

Reputation: 1018

If you want to "Alert" the url you can do that by using alert function onClick event as shown in code below. Look at this plnkr for working demo.

d3.json("data.json", function(error, root) {
        if (error) throw error;

        var focus = root,
        nodes = pack.nodes(root),
        view;

        var circle = svg.selectAll("circle")
        .data(nodes)
        .enter().append("circle")
        .attr("class", function(d) { return d.parent ? d.children ? "node" : "node node--leaf" : "node node--root"; })
        .style("fill", function(d) { return d.children ? color(d.depth) : null; })
        .on("click" , function(d) {

            console.log(d.url);
            alert(d.url);
            return d;
        })

Upvotes: 0

Related Questions