Adithya
Adithya

Reputation: 339

How to user JSON arrays with d3

I am new with d3 and json. I am trying to construct a horizontal gantt chart. Earlier I have acieved the same using inline arrays which i stored in var dataset. But now I have replaced the arrays with json object array .

[   {
        "process" :"process-name 1",
        "stage" : "stage name 1",
        "activities": [
            {
            "activity_name": "waiting",
            "start": new Date('2012-12-10T06:45+05:30'),
            "end": new Date('2012-10-10T08:45+05:30'),
            },
            {
            "activity_name": "processing",
            "start": new Date('2012-10-11T05:45+05:30'),
            "end": new Date('2012-10-11T06:45+05:30'),
            },
            {
            "activity_name": "pending",
            "start": new Date('2012-10-12T11:45+05:30'),
            "end": new Date('2012-10-13T12:45+05:30'),
            }
            ]

    },
    {
        "process" :"process-name 2",
        "stage" : "stage name 2",
        "activities": [
            {
            "activity_name": "waiting",
            "start": new Date('2012-10-22T06:45+05:30'),
            "end": new Date('2012-10-23T08:45+05:30'),
            },
            {
            "activity_name": "processing",
            "start": new Date('2012-10-25T05:45+05:30'),
            "end": new Date('2012-10-25T06:45+05:30'),
            },
            {
            "activity_name": "pending",
            "start": new Date('2012-10-27T11:45+05:30'),
            "end": new Date('2012-10-27T12:45+05:30'),
            }
            ]
    }       

    ];

The d3 part of the code to draw the rectangle is this :

console.log(dataset);

var height = 600;
var width = 500;
var x = d3.time.scale().domain([new Date(2011, 0, 1,23,33,00), new Date(2013, 0, 1, 23, 59)]).range([0, width]);



var svg = d3.selectAll("body")
.append("svg")
.attr("width",width)
.attr("height",height)
.attr("shape-rendering","crispEdges");


temp = svg.selectAll("body")
.data(dataset) // LINE 1 
.enter()


temp.append("rect")
.attr("width", 4)
.attr("height",12)
.attr("x", function(d) {return x(d.activities[0].start)}) // LINE 2
.attr("y",function(d,i){return i*10;})
.attr("fill","steelblue");

I have following questions :

  1. I want to access START date inside activities but with the code lines (marked LINE 1 and LINE 2) I have written it is giving only 2 rectangles for first start of each activity . WHY?

  2. In LINE 1 can I use dataset.actitvies instead of just dataset? I tried using that , gave me this error :

Uncaught TypeError: Cannot read property '0' of undefined

Upvotes: 2

Views: 5204

Answers (1)

Andrew Kirkegaard
Andrew Kirkegaard

Reputation: 1684

  1. Because the length of dataset is 2, so when you join it with your rects you're only going to get 2 rects.

  2. You can use dataset.activities, but you would change LINE 2 to

    .attr("x", function(d) {return x(d.start)})

because you've changed the join so that d now refers to the activities. However, if you do that, you're just going to get three rectangles -- the activities for one of your projects.

If you're going to use nested data, you either need to use a nested selection or you need to flatten the data first by adding all activities to a simple array.

var data = [];

for (var i = 0, len = dataset.length; i < len; i++) {
    data = data.concat(dataset[i].activities);
}

A nested selection would look something like this:

projects = svg.selectAll("g")
    .data(dataset)
  .enter().append("g")
    .attr("transform", function (d, i) { return "translate(0," + (i * 10) + ")"; }),

rects = projects.selectAll("rect")
    .data(function (d) { return d.activities; })
  .enter().append("rect")
    .attr("height", 12)
    .attr("width", 4)
    .attr("x", function (d) { return x(d.start); })

EDIT: here's a jsfiddle

Upvotes: 3

Related Questions