Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dc.js access data points in multiple charts when click datapoint in first chart

Tags:

dc.js

Using different dimensions of the same dataset, there are three dc.js Line Charts on screen.

When user clicks a datapoint on any lineChart, I wish to locate and return the data values for that corresponding point from all other charts, including the one clicked on.

I am also attempting (on mouseover) to change the circle fill color to red for the datapoint being hovered, as well as for the corresponding datapoint (same "x" value) for all other charts.

I am using the .filter() method but haven't been successful getting the desired data. The error message is: "Uncaught TypeError: myCSV[i].filter is not a function"

Full jsFiddle demo/example

lc1.on('renderlet', function(lc1) {
  var allDots1 = lc1.selectAll('circle.dot');
  var allDots2 = lc2.selectAll('circle.dot');
  var allDots3 = lc3.selectAll('circle.dot');
  allDots1.on('click', function(d) {
     var d2find = d.x;
     var d2find2 = d3.select(this).datum();
     console.log(myCSV);
     alert('Captured:'+"\nX-axis (Date): "+d2find2.x +"\nY-axis (Value): "+ d2find2.y +"\nDesired: display corresponding values from all three charts for this (date/time) datapoint");
     allDots2.filter(d=>d.x == d2find2).attr('fill','red');
     findAllPoints(d2find2);
  });//END allDots1.on(click);

  function findAllPoints(datum) {
     var objOut = {};
     var arrLines=['car','bike','moto'];
     for (var i = 0; i < 3; i++) {
        thisSrx = arrLines[i];
        console.log('thisSrx: '+thisSrx);
        console.log(myCSV[i].date)
        console.log(datum.x);
        //loop thru myCSV obj, compare myCSV[i].date to clicked "x" val
        //build objOut with data from each graph at same "X" (d/t) as clicked
        objOut[i] = myCSV[i].filter(e => e.date === datum.x)[0][thisSrx];
     }
     $('#msg').html( JSON.stringify(objOut) );
     console.log( JSON.stringify(objOut) );
  }//END fn findAllPoints()

});//END lc1.on(renderlet)
like image 707
crashwap Avatar asked Feb 12 '17 23:02

crashwap


1 Answers

myCSV contains all three data points, so I don't see the need to loop through the three charts independently - findAllPoints is going to find the same array entry for all three data series anyway.

The main problem you have here is that date objects don't compare equal if they have the same value. This is because == (and ===) evaluate object identity if the operands are objects:

> var d1 = new Date(), d2 = new Date(d1)
undefined
> d1
Mon Feb 13 2017 09:03:53 GMT-0500 (EST)
> d2
Mon Feb 13 2017 09:03:53 GMT-0500 (EST)
> d1==d2
false
> d1.getTime()===d2.getTime()
true

There are two ways to deal with this.

Approach 1: use second event argument

If the items in all the charts match up item by item, you can just use the index.

All d3 callbacks pass both the datum and the index. So you can modify your callback like this:

allDots1.on('click', function(d,i) {
  // ...
  allDots2.filter((d,j)=> j===i).attr('fill','red').style('fill-opacity', 1);
  alert(JSON.stringify(myCSV[i]));
});

http://jsfiddle.net/gordonwoodhull/drbtmL77/7/

Approach 2: compare by date

If the different charts might have different data indices, you probably want to compare by date, but use Date.getTime() to get an integer you can compare with ===:

allDots1.on('click', function(d) {
  var d2find = d.x;
  // ...
  allDots2.filter(d=> d.x.getTime()===d2find.getTime()).attr('fill','red').style('fill-opacity', 1);
  var row = myCSV.filter(r=>r.date.getTime()===d2find.getTime())
  alert(JSON.stringify(row));
});

http://jsfiddle.net/gordonwoodhull/drbtmL77/10/

Note that in either case, you're going to need to also change the opacity of the dot in the other charts, because otherwise they don't show until they are hovered.

Not sure when you want to reset this - I guess it might make more sense to show the corresponding dots on mouseover and hide them on mouseout. Hopefully this is enough to get you started!

like image 135
Gordon Avatar answered Nov 08 '22 17:11

Gordon