dc.js charts not linked - d3.js

I have two barCharts exactly equivalent except for the .brushOn option :
pnlPerDaybarChart
.height(300)
.width(700)
.dimension(dims.date)
.group(groups.date.pnlSum)
.valueAccessor(function(d) {
return Math.abs(d.value);
})
.renderTitle(false)
.x(d3.time.scale().domain([minDate,maxDate]))
.xUnits(d3.time.days)
.colors(colorChoice)
.colorAccessor(colorAccessorPosNeg)
.brushOn(false)
.elasticY(true)
.margins({left: 70 ,top: 10, bottom: 30, right: 50})
.centerBar(true);
pnlPerDaybarChartBrush
.height(100)
.width(700)
.dimension(dims.date)
.group(groups.date.pnlSum)
.valueAccessor(function(d) {
return Math.abs(d.value);
})
.renderTitle(false)
.x(d3.time.scale().domain([minDate,maxDate]))
.xUnits(d3.time.days)
.colors(colorChoice)
.colorAccessor(colorAccessorPosNeg)
.brushOn(true)
.elasticY(true)
.margins({left: 70 ,top: 10, bottom: 30, right: 50})
.centerBar(true);
They render the way I expect but when I use the brush on pnlPerDaybarChartBrush, dc.js doesn't update the other one.
Also, clicking on a bar in pnlPerDaybarChart doesn't modify pnlPerDaybarChartBrush rendering (or any of the other charts on the webpage).
Is this the expected behaviour ?
What I was expecting is :
when I click on a single day in the chart without brush it
automatically renders all charts with data for that specific day.
when I use the brush it also renders the filtered chart without brush
Here is the jsFiddle

It doesn't look like dc.js bar charts support click-to-filter by default. The brush function is expected to be the way you filter a bar or line chart (but as you've discovered, it has its own complications).
If your data is too dense to filter it precisely with the brush, one option would be to allow the user to zoom in on the range chart with mouse or touch events:
http://jsfiddle.net/r4YBS/4/
The only change is adding
.mouseZoomable(true);
at the end of the definition of the brushable bar chart.
Alternately you could implement a custom click listener, which then calls the .filter() method directly.

Fiddle for your requirement.
You are of course right.
.rangeChart is the property you'd need to use it.
Hope it helps.

Related

How to dynamically change bin size in bar chart (dc.js)?

So I am calling the below code multiple times but the issue is that the bar chart bin size is stuck to the first data that I am putting in rest everything is changing as it should but not the bin size.
barChart
.width(1080)
.height(138)
.margins({top: 10, right: 10, bottom: 20, left: 50})
.dimension(key_map[$(this).text()].Dim)
.group(key_map[$(this).text()].Group)
.colors(['#6baed6'])
.x(d3.scale.ordinal().domain(key_map[$(this).text()].Dim))
.xUnits(dc.units.ordinal)
.elasticY(true)
.yAxis().ticks(4);
barChart.elasticX(true).filterAll();dc.redrawAll();
Thanks to #Gordon, I finally figured it out.
The array of keys was getting ignored even though I was calling elasticX(true); So I ended up calling chart.focus([all_the_keys_from_the group]); And it works perfectly now.
barChart
.dimension(key_map[$(this).text()].Dim)
.group(key_map[$(this).text()].Group)
.x(d3.scale.ordinal().domain(key_map[$(this).text()].Dim))
.xUnits(dc.units.ordinal)
.elasticX(true);
var focus_keys = [];
key_map[$(this).text()].Group.all().forEach(element => {
focus_keys.push(element.key);
});
barChart.focus(focus_keys);
barChart.filterAll(); dc.redrawAll();

Is it possible to have a scrolling div that adjusts to the number of bars in a dc.js rowchart

I have several rowcharts that are connected to each other with dc.js.
These rowcharts have the x axis at the top in a different div, as explained here. However these rowcharts also implement filtering and removing, therefore, whenever I filter in one rowchart, the number of bars in the others reduce, but it maintains the size of the scrollable div, even though there are no bars below what is shown. Also, I'm pretty sure it is easy, but I haven't figured out how to put the reset button below the chart, because it shows between the chart div and the axis div, as seen below.
Is there a way to correct these issues?
This is what I have in each rowchart div:
<div id='axis'></div>
<div id="chart" style="overflow-y:auto; height:200px;">
<div>
<span class="reset" style="display: none;">Phylum seleccionado(s):
<span class="filter"></span>
<a class="reset" href="javascript:Chart.filterAll();dc.redrawAll();" style="display">Reset</a>
</span>
</div>
</div>
And this is what a I have in each rowchart in the main.js:
Chart
.fixedBarHeight(20)
.height(nonEmpty.all().length * 20 + 1)
.margins({top: 0, right: 20, bottom: 0, left: 20})
.width(600)
.xAxis(d3.axisTop())
.elasticX(true)
.ordinalColors(['#e41a1c'])
.gap(1)
.dimension(Dim)
.group(nonEmpty) //this removes the ones that don't match the filter of the other rowchart
.on('pretransition', function () {
Chart.select('g.axis').attr('transform', 'translate(0,0)');
Chart.selectAll('line.grid-line').attr('y2', Chart.effectiveHeight());
});
Partial answer here. Well, it answers what you asked but doesn't answer the next question I expect. :(
You are currently sizing the chart based on the number of bars, and you will need to resize the chart when the number of bars change.
This should be done in a preRedraw handler, but unfortunately preRedraw is currently fired after resizing is done. So currently you have to override .redraw():
dc.override(chart, 'redraw', function() {
chart.height(chart.group().all().length * 21);
return chart._redraw();
})
As for putting the info & controls after the chart, there are two issues and I was only able to solve one of them.
dc.js will append an svg element to the chart div. It'd be nice to have more control over this but I'm not sure what to do. For the moment, the easiest workaround is to re-append the info div:
chart.on('postRender', function() {
chart.root().node().appendChild(chart.select('div.info').node())
})
However, what you really want is probably to pull the info div out of the scrolling div, and I can't figure that out at the moment. The problem is that the chart expects the controls/info to be inside the chart div, and that's the same one that needs to scroll.
I tried to mess around with adding another scrolling div inside the chart div, and then moving the svg under it. This works, but it creates some annoying flashing.
Here's what I got so far. I may return to this later if I think of a better solution.
Update: controls outside of the scroller
To solve this right, we need the controls outside of the chart div.
We can port baseMixin.turnOnControls to a filtered event handler, and do the same showing and populating that the chart would do:
function turnOnControls(_chart, controls) {
var attribute = _chart.controlsUseVisibility() ? 'visibility' : 'display';
controls.selectAll('.reset').style(attribute, null);
controls.selectAll('.filter').text(dc.printers.filters(_chart.filters())).style(attribute, null);
}
function turnOffControls(_chart, controls) {
var attribute = _chart.controlsUseVisibility() ? 'visibility' : 'display';
var value = _chart.controlsUseVisibility() ? 'hidden' : 'none';
controls.selectAll('.reset').style(attribute, value);
controls.selectAll('.filter').style(attribute, value).text(_chart.filter());
}
function filter_function(controls) {
return chart => {
chart.hasFilter() ?
turnOnControls(chart, controls) :
turnOffControls(chart, controls);
}
}
chart.on('filtered', filter_function(d3.select('#info')));
Also, controlsUseVisibility and visibility: hidden is better when the controls will affect layout when shown/hidden.
(fiddle)

are there any way to change c3js stacked area chart opacity on mouse hover

I have a question regarding c3.js.
Currently, we are using c3js to display a stacked area chart, that is pretty fine, but our client asked us if we can change the individual area's opacity when customer is mouse hovering one area.
I could not find any solution for this, and hope to hear your suggetions.
Thanks
Try adding this after you've set up your chart -->
d3.selectAll(".c3-area")
.style ("pointer-events", "all")
.on("mouseover", function (d) { return d3.select(this).style("opacity", 0.6)})
.on("mouseout", function (d) { return d3.select(this).style("opacity", 0.2)})
;
The pointer-events setting is the important bit as by default most of the elements in the c3 chart are styled to ignore them.
Add it to the end of the c3 example to see it working --> https://c3js.org/samples/chart_area.html

jqPlot donut chart with legends issue

I have jqplot donut chart where I want to add chart labels in the center part. Also want to add scrolling for labels in the middle of graph. So only 1-2 labels in the center will be visible and rest will be visible when user scrolls.
Please have a look attached image. As per my knowledge, we can't add labels in the center of chart. Is there any way to do this? Appreciate your help.
My current code is as below:
<script type="text/javascript">
var _chart5_plot_properties;
_chart5_plot_properties = {
title: " ",
"seriesDefaults":{
renderer:$.jqplot.DonutRenderer,
rendererOptions:{
sliceMargin: 0,
innerDiameter: 220,
startAngle: -90,
barPadding: 0,
padding: 3,
}
},
grid: {
shadow: false,
drawBorder: false,
shadowColor: "transparent"
},
highlighter: {
show: true,
tooltipLocation: "sw",
useAxesFormatters:false
}
}
plot2 = $.jqplot("chart2", chart_data, _chart5_plot_properties);
I couldn't find an option for this in jqPlot.
Though, jqPlot has 8 options to position the legend, but it does not have the center option. jqPlot Legend Locations
But after tweaking it a bit, I could accomplish it using jQuery. Since we need to require jQuery to render/draw jqPlot charts, so I thought of using jQuery rather than pure Javascript.
I have used two functions defineDimensionsForLegendTable(parentContainerID, dimensions) and fixLegendsToCenter(parentContainerID)
Other important things that you should not miss out while using these functions
Make sure you include the jquery.jqplot.js, jqplot.pieRenderer.js, jqplot.donutRenderer.js, jquery.jqplot.css files (or the minified versions - .min.js)
Set placement to outsideGrid in legendOptions
legend: { show:true, placement: 'outsideGrid' }
Give a higher z-index to the legend-table
#chart2 .jqplot-table-legend{
z-index: 99999;
}
Find the working fiddle here - jqPlot Donut Chart with legend in the center
Note: If the chart does not show up in Google Chrome, try opening it in Firefox or some other browser.
Remove the console.log lines from the code ;-)
You can use Foundation or Bootstrap to beautify the scrollbar. :-)
Hope it helps :-)

In jqplot, how to show x-axis on top, and how to hide axis label

I have a jqplot object that has x-axis tick marks/labels rendered on bottom. Basically, there is a stack of charts, all using the same x-axis. I would like to reclaim the bottom axis area from the middle charts for the plot lines.
How can I dynamically relocate the x-axis to top (i.e., northward)
How to make the x-axis label go away? For this I tried
plotobject.axes.xaxis.showLabel = false;
plotobject.replot();
but that seems to have no visible effect. plotobject is what's returned by the original $.jqplot() call and I am using $.jqplot.DateAxisRenderer for xaxis.renderer. I have access only to the plot object.
Thanks
This simple CSS solution is working for me to put the x-axis labels on top of the chart.
.jqplot-xaxis {
position: relative;
top: -30px;
}
well, the label for each axis (which is the axis title) has it's own renderer, and thus it's own options. I use the plugin one ( http://www.jqplot.com/docs/files/plugins/jqplot-canvasAxisLabelRenderer-js.html ) but also the default has a show: true/false setting. ( http://www.jqplot.com/docs/files/jqplot-axisLabelRenderer-js.html )
it should look something like this:
axes: {
xaxis: {
labelRenderer: $.jqplot.CanvasAxisLabelRenderer,
label: 'Dates',
labelOptions: {
show: true,
fontSize: '10pt'
},
}
}
For putting the x-axis on top, I'm not sure what your problem realy is, but I try to select it with jquery and set it's z-index to something high to bring it on top. Take a look at http://www.jqplot.com/docs/files/jqPlotCssStyling-txt.html for some selection ideas.

Resources