In a multi-chart dc.js/d3.js presentation, I wish to trap user click on a datapoint in the first chart, and:
For example, user clicks on shift 2 on first chart. 140 cars were built on that shift. In chart 1, three shifts are within 30 of that shift's production: 2, 7, 10. I wish to make those 3 data points green, and then also make shifts 2, 7, 10 green in both charts 2 and 3 also. (Also, the original clicked-on datapoint should be red)
I am unsure how to add the greendot class to those three datapoints in the three charts.
jsFiddle to work with
clearconsole();
var chartWidth = 500;
var myCSV = [
{"shift":"1","date":"01/01/2016/08/00/00","car":"178","truck":"125","bike":"317","moto":"237"},
{"shift":"2","date":"01/01/2016/17/00/00","car":"125","truck":"189","bike":"125","moto":"273"},
{"shift":"3","date":"02/01/2016/08/00/00","car":"140","truck":"219","bike":"328","moto":"1252"},
{"shift":"4","date":"02/01/2016/17/00/00","car":"222","truck":"290","bike":"432","moto":"378"},
{"shift":"5","date":"03/01/2016/08/00/00","car":"200","truck":"250","bike":"420","moto":"319"},
{"shift":"6","date":"03/01/2016/17/00/00","car":"230","truck":"220","bike":"310","moto":"413"},
{"shift":"7","date":"04/01/2016/08/00/00","car":"155","truck":"177","bike":"377","moto":"180"},
{"shift":"8","date":"04/01/2016/17/00/00","car":"179","truck":"203","bike":"405","moto":"222"},
{"shift":"9","date":"05/01/2016/08/00/00","car":"208","truck":"185","bike":"360","moto":"195"},
{"shift":"10","date":"05/01/2016/17/00/00","car":"150","truck":"290","bike":"315","moto":"280"},
{"shift":"11","date":"06/01/2016/08/00/00","car":"200","truck":"220","bike":"350","moto":"205"},
{"shift":"12","date":"06/01/2016/17/00/00","car":"230","truck":"170","bike":"390","moto":"400"},
];
console.log('Click on a datapoint in chart1 to begin ');
lc1 = dc.lineChart("#line1");
lc2 = dc.lineChart("#line2");
lc3 = dc.lineChart("#line3");
var dateFormat = d3.time.format("%d/%m/%Y/%H/%M/%S");
myCSV.forEach(function (d) {
d.date = dateFormat.parse(d.date);
});
myCSV.forEach(function (d) {
d['car'] = +d['car'];
d['bike'] = +d['bike'];
d['moto'] = +d['moto'];
});
//console.log(myCSV);
var facts = crossfilter(myCSV);
var dateDim = facts.dimension(function (d) {return d.date});
var carDim = facts.dimension(function (d) {return d['car']});
var dgCar = dateDim.group().reduceSum(function (d) {return d['car']});
var bikeDim = facts.dimension(function (d) {return d['bike']});
var dgBike = dateDim.group().reduceSum(function (d) {return d['bike']});
var motoDim = facts.dimension(function (d) {return d['moto']});
var dgMoto = dateDim.group().reduceSum(function (d) {return d['moto']});
var minDate = new Date ("2016-01-01T08:00:00.000Z");
var maxDate = new Date ("2016-01-06T17:00:00.000Z");
var maxY = d3.max(myCSV, function(d) {return d['car']});
lc1
.renderArea(false)
.width(chartWidth)
.height(250)
.dimension(dateDim)
.group(dgCar)
.defined(function(d) {if(d.y !==null) {return d.y;}})
.transitionDuration(1000)
.margins({top: 30, right: 20, bottom: 35, left: 60})
.yAxisLabel('Cars')
.renderHorizontalGridLines(true)
.brushOn(false)
.x(d3.time.scale().domain([minDate,maxDate]));
lc1.yAxis().ticks(5);
lc1.xAxis().ticks(3);
lc2
.renderArea(false)
.width(chartWidth)
.height(250)
.dimension(dateDim)
.group(dgBike)
.defined(function(d) {if(d.y !==null) {return d.y;}})
.transitionDuration(1000)
.margins({top: 30, right: 20, bottom: 35, left: 60})
.yAxisLabel('Bikes')
.renderHorizontalGridLines(true)
.brushOn(false)
.x(d3.time.scale().domain([minDate,maxDate]));
lc2.yAxis().ticks(5);
lc2.xAxis().ticks(3);
lc3
.renderArea(false)
.width(chartWidth)
.height(250)
.dimension(dateDim)
.group(dgMoto)
.defined(function(d) {if(d.y !==null) {return d.y;}})
.transitionDuration(1000)
.margins({top: 30, right: 20, bottom: 35, left: 60})
.yAxisLabel('Motos')
.renderHorizontalGridLines(true)
.brushOn(false)
.x(d3.time.scale().domain([minDate,maxDate]));
lc3.yAxis().ticks(5);
lc3.xAxis().ticks(3);
lc1.on('renderlet', function(lc1) {
console.log('myCSV.length: '+myCSV.length);
var allDots1 = lc1.selectAll('circle.dot');
var allDots2 = lc2.selectAll('circle.dot');
var allDots3 = lc3.selectAll('circle.dot');
allDots1.on('click', function(d,i) { //i==index, d==obj of clicked point
console.log(JSON.stringify(myCSV[i]));
var arrWeeks = [];
allDots1.filter((d,j)=> j===i).classed('reddot');
for (var xx=0;xx<myCSV.length;xx++){
var t1 = myCSV[xx].car - d.y;
var t2 = d.y - myCSV[xx].car;
var looptest = (t1<30 && t1>0) || (t2<30 && t2>0);
console.log(myCSV[xx].car +' (loop val) is/not within 30 of '+d.y+ '(clicked val)' + looptest);
if ( (t1<30 && t1>0) || (t2<30 && t2>0) ){
arrWeeks.push(xx); //All index points in "Cars" that are within 30 of clicked point
}
//Next line doesn't work:
//allDots2.filter((d,j)=> j===xx).classed('greendot').style('fill-opacity', 1);
}//ENDFOR
console.log("%s %o", 'arrWeeks: ', arrWeeks);
/*
Loop through all 3 "allDotsN" d3 collections and add
greendot class to each circle that is at one of the
index values in arrWeeks. For example, if arrWeeks contains
[2,4,6] then the 3rd, 5th and 7th dot points in all three
graphs should be green (and the original clicked-on datapoint should be red)
*/
// allDots1.filter((d,j)=> j===arrWeeks[]).classed('greendot').style('fill-opacity', 1);
// allDots2.filter((d,j)=> j===arrWeeks[]).classed('greendot').style('fill-opacity', 1);
// allDots3.filter((d,j)=> j===arrWeeks[]).classed('greendot').style('fill-opacity', 1);
});//END allDots1.on(click);
});//END lc1.on(renderlet)
dc.renderAll();
dc.redrawAll();
function clearconsole(){
console.API;
if (typeof console._commandLineAPI !== 'undefined') {
console.API = console._commandLineAPI; //chrome
} else if (typeof console._inspectorCommandLineAPI !== 'undefined') {
console.API = console._inspectorCommandLineAPI; //Safari
} else if (typeof console.clear !== 'undefined') {
console.API = console;
}
console.API.clear();
}
svg{height:280px;width:500px;}
.greendot{stroke:green !important; fill:green !important; fill-opacity:1 !important;}
.reddot{stroke:red !important; fill:red !important; fill-opacity:1 !important;}
<script src="http://cdnjs.cloudflare.com/ajax/libs/d3/3.3.3/d3.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.1/crossfilter.min.js"></script>
<script src="http://dc-js.github.io/dc.js/js/dc.js"></script>
<link href="http://dc-js.github.io/dc.js/css/dc.css" rel="stylesheet"/>
<svg id="line1"></svg>
<svg id="line2"></svg>
<svg id="line3"></svg>
Use .classed('yourclass', true)
, see docs:
allDots1.on('click', function(d, i) { //i==index, d==obj of clicked point
console.log(JSON.stringify(myCSV[i]));
var arrWeeks = [i];
for (var xx = 0; xx < myCSV.length; xx++) {
var t1 = myCSV[xx].car - d.y;
var t2 = d.y - myCSV[xx].car;
var looptest = (t1 < 30 && t1 > 0) || (t2 < 30 && t2 > 0);
console.log(myCSV[xx].car + ' (loop val) is/not within 30 of ' + d.y + '(clicked val)' + looptest);
if ((t1 < 30 && t1 > 0) || (t2 < 30 && t2 > 0)) {
arrWeeks.push(xx); //All index points in "Cars" that are within 30 of clicked point
}
} //ENDFOR
console.log("%s %o", 'arrWeeks: ', arrWeeks);
allDots1.classed('reddot', false);
allDots1.classed('greendot', false);
allDots2.classed('greendot', false);
allDots3.classed('greendot', false);
arrWeeks.forEach((i) => {
allDots1.filter((d, j) => j === i).classed('greendot', true);
allDots2.filter((d, j) => j === i).classed('greendot', true);
allDots3.filter((d, j) => j === i).classed('greendot', true);
});
allDots1.filter((d, j) => j === i).classed('reddot', true);
});
Working demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With