how to focus the clicked bar in C3.js bar graph? - javascript

I have this code which makes a graph using c3.js : https://jsfiddle.net/1bxe2scd/
<!DOCTYPE html>
<html>
<head>
<title>Dsnap - Charts</title>
<!-- Load c3.css -->
<link href="c3/c3.css" rel="stylesheet" type="text/css">
<!-- Load d3.js and c3.js -->
<script src="d3/d3.min.js" charset="utf-8"></script>
<script src="c3/c3.min.js"></script>
</head>
<body>
<div id="chart" style="width:480px;height:400px"></div>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script>
var chart = c3.generate({
bar: {
width: 15
},
padding: {
left: 60
},
data: {
x: 'Date',
columns:
[
['Date', '2011-02','2013-01','2013-02','2013-03','2013-04','2013-05','2013-06','2013-07','2013-08','2013-09','2013-10','2013-11','2013-12','2014-01','2014-02'],
['value', 777,53,165,269,344,376,410,421,405,376,359,392,433,455,978]
],
type: 'bar',
onclick: function(e) { console.log(e.x);}
},
axis: {
rotated: true,
x: {
type: 'category'
}
},
tooltip: {
grouped: false
},
legend: {
show: false
}
});
</script>
</body>
</html>
I want the bar on which the user clicks to be focused and the rest of the bar should become faded, how can I achieve that?
How can I get the Y value of the clicked bar(eg: 2011-02 etc)?

You can do this for highlighting the bar:
onclick: function(e) {
//make all the bar opacity 0.1
d3.selectAll(".c3-shape").style("opacity",0.1);
var k = ".c3-shape-"+ e.index;
//make the clicked bar opacity 1
d3.selectAll(k).style("opacity",1)
}
Working code here
On clicking out side in the chart if you wish to bring back all the bars attach the click listener to the chart and on click make all bar's opacity 1:
d3.selectAll("#chart").on("click", function(d) {
//reset all the bars
d3.selectAll(".c3-shape").style("opacity", 1);
})
Working code here
EDIT
So now since you have two charts specify the id also to make it specific to the chart note the id in the selector: (#chart/#chart1):
d3.selectAll("#chart1").on("click", function(d) {
//reset all the bars for chart1
d3.selectAll("#chart1 .c3-shape").style("opacity", 1);
})
d3.selectAll("#chart").on("click", function(d) {
//reset all the bars for chart
d3.selectAll("#chart .c3-shape").style("opacity", 1);
})
On click for chart1 bar will look like this:
onclick: function(e) {
//make all the bar opacity 0.1 for chart1
d3.selectAll("#chart1 .c3-shape").style("opacity", 0.1);
var k = "#chart1 .c3-shape-" + e.index;
//make the clicked bar opacity 1
d3.selectAll(k).style("opacity", 1)
event.stopPropagation()
}
Working code here
Hope this helps!

C3 has callbacks, for specifying what should happen when a click (or mouseover/mouseout) event occurs:
http://c3js.org/reference.html#data-onclick
It also has "APIs": functions you can call to basically act like the user made a selection or focused:
http://c3js.org/reference.html#api-focus
You could hook one of these up to trigger the other, like have the onclick() function call focus().
But given what you're precisely looking for, the impediment would be that the focus() function doesn't accept the indices of individual bars on the graph. So it can only highlight an entire column/series of data at once, not individual bars. Here's the GitHub issue:
https://github.com/c3js/c3/issues/1389

Related

morris.js line update ymin

Is there any way to update the ymin of a morris.js line/area?
I've tried it with:
chart.ymin = 10
but the ymin is still 0.
When it`s not possible in morris.js, are there any other chart libarys that include such a feature?
Solution 1
Make sure you set the Morris parameter resize to true.
Then, on your action, you can set the ymin, redraw the chart and make sure the chart is well positioned (trigger a window resize):
chart.ymin = 10;
chart.redraw();
$(window).trigger("resize");
Please try the following snippet:
var data = [
{ Date: '2016-01-01', Sales: 10 },
{ Date: '2016-01-02', Sales: 20 },
{ Date: '2016-01-03', Sales: 40 },
{ Date: '2016-01-04', Sales: 5 },
{ Date: '2016-01-05', Sales: 50 }
];
var chart = new Morris.Line({
element: 'chartLine',
data: data,
xkey: 'Date',
ykeys: ['Sales'],
labels: ['Sales'],
resize: true,
xLabels: 'day',
parseTime: false
});
$(".ymin").on("click", function() {
chart.ymin = 10;
chart.redraw();
$(window).trigger("resize");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.min.js"></script>
<link href="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.css" rel="stylesheet" />
<div id="chartLine"></div>
<div class="ymin">Set ymin</div>
Solution 2
Set the Morris parameter resize to false for your temperature chart.
Make sure you include the Morris CSS available on the Morris GitHub. Without this CSS, hovering the chart will display the data at the bottom of the chart and will hide the x axis on the next data update from the setInterval.
Remove the code trying to get/set the chart height, triggering a window resize and calling the temperature chart redraw.
Finally add the following code in your $(document).ready function:
var delay = (function () {
var timer = 0;
return function (callback, ms) {
clearTimeout(timer);
timer = setTimeout(callback, ms);
};
})();
$(window).resize(function () {
delay(function () {
TemperatureChart.redraw();
}, 300);
}).trigger('resize');
Please try the following fork of your CodePen: codepen.io/krlzlx/pen/prwMLr

use specific kendo chart library files instead of kendo.all.min.js

I am using Kendo chart in my application, for this "kendo.all.min.js" is used
but size of this file is 2.5 MB, and i want to optimize the speed performance of application therfore i want only specific kendo chart library,
I am using following library instead of kendo.all.min.js.
<script src="scripts/kendo/kendo.core.min.js"></script>
<script src="scripts/kendo/kendo.data.min.js"></script>
<script src="scripts/kendo/kendo.userevents.min.js"></script>
<script src="scripts/kendo/kendo.color.min.js"></script>
<script src="scripts/kendo/kendo.pdf.min.js"></script>
<script src="scripts/kendo/kendo.drawing.min.js"></script>
<script src="scripts/kendo/kendo.dataviz.core.min.js"></script>
<script src="scripts/kendo/kendo.dataviz.themes.min.js"></script>
<script src="scripts/kendo/kendo.dataviz.chart.min.js"></script>
<script src="scripts/kendo/kendo.dataviz.chart.polar.min.js"></script>
<script src="scripts/kendo/kendo.dataviz.chart.funnel.min.js"></script>
And When i run application it throws error "Origin are not define"
$("#chart").kendoChart({
legend: {
position: "bottom",
item: {
visual: createLegendItem
}
},
seriesDefaults: {
type: "line",
style: "smooth",
visual: function (e) {
return createColumn(e.rect, "#6e6e78");//#0099CC")// e.options.color);
}
},
series: [{
type: "column",
data: a,b,c,d,
labels: {
visible: true,
position: "outsideEnd",
visual: function (e) {
console.log(e);
var rect;
//if (checkScreenSize()) {
// rect = new kendo.geometry.Rect(
// [e.rect.origin.x, e.rect.origin.y], // Position of the top left corner
// [25,25] // Size of the rectangle
// );
//} else {
rect = new kendo.geometry.Rect(
[e.rect.origin.x - position, e.rect.origin.y], // Position of the top left corner
[size, size] // Size of the rectangle
);....
Please let me know where i am wrong and which files i missed to include.
use kendo.custom.min.js file before above files, it will work

c3.js tooltip - make static and style

I have a c3.js stacked barchart that updates when you hover over a Leaflet map, and I need the tooltip to be static as otherwise the user will hover over other areas of the map and change the data in the barchart, before actually reaching it. However, I'm new to coding and especially new to C3 and I can't get around how to make the tooltip static. Also, does anyone know how to style the tooltip later? I have only found very complex examples online, but it feels like I should be able to do it somewhere after I generate the chart.
Any help would be much appreciated!
Here is my code:
function getMiniChartData(properties) {
var values = [
['rape', rape[properties['gss_code']]],
['other sexual', other_sexual[properties['gss_code']]]];
console.log(values);
return values;
}
var chart;
function drawMiniChart(properties) {
console.log('drawing mini chart');
var data = getMiniChartData(properties);
chart = c3.generate({
bindto: '#minichart',
color: {
pattern: ['#E31A1C', '#BD0026']
},
point: {
show: false
},
tooltip: {
show: true
},
data: {
columns: data,
type: 'bar',
groups: [
['rape', 'other sexual']
]
},
axis: {
y: {
max:60,
min:0
}
},
grid: {
y: {
lines: [{
value: 0
}]
}
}
});
}
function updateMiniChartData(properties) {
console.log('updating mini chart');
var data = getMiniChartData(properties);
chart.load({
columns: data
});
}
Just edit the position in the tooltip :
position: function () {
var position = c3.chart.internal.fn.tooltipPosition.apply(this, arguments);
position.top = 0;
return position;
}
This will set the tooltip to always be at the top of the point. So it stays at the same y coordinate (top:0) but follows the points x value. You could go further and set it to stay at one position on the page.
Check this fiddle I have put together : http://jsfiddle.net/thatOneGuy/owhxgaqm/185/
This question will help you out : C3 charts - contents of tooltip clickable
If you want it visible all the time just add this code :
var originalHideTooltip = chart.internal.hideTooltip
chart.internal.hideTooltip = function () {
setTimeout(originalHideTooltip, 100)
};

Using Flot with multiple bars with orderbars.js and categories

I am having trouble creating multiple bars with flot. There is a plugin that can be downloaded here: http://www.benjaminbuffet.com/public/js/jquery.flot.orderBars.js that makes graphs with multiple bars per x category like this: http://www.pikemere.co.uk/blog/tutorial-flot-how-to-create-bar-charts/ (see under the customized bar charts). However, his example is a bit different in that it uses the time function rather than categories.
Here is my code:
<!doctype html>
<head>
<script language="javascript" type="text/javascript" src="/flot/jquery.js"></script>
<script language="javascript" type="text/javascript" src="/flot/jquery.flot.js"> </script>
<script language="javascript" type="text/javascript" src="/flot/jquery.flot.categories.js"></script>
<script language="javascript" type="text/javascript" src="/flot/jquery.flot.orderBars.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var data1 = [
{
label: "Male" ,
data: [["True", 1],["False", 2]] ,
bars: {
show: true,
barWidth: 0.13,
order: 1
}
},
{
label: "Female" ,
data: [["True", 3],["False", 4]],
bars: {
show: true,
barWidth: 0.13,
order: 2
}
}
];
$.plot($("#placeholder"), data1, {
xaxis: {
mode: "categories"
},
});
});
</script>
<title>Test</title>
</head>
<body>
<div id="placeholder" style="width:600px;height:300px"></div>
</body>
</html>
With the above code, the graph displays, but without any bars. If I remove the order:1 and order:2, it displays correctly, except with the bars overlapping each other rather than being offset by each other (I think it just ignores the orderbars plugin).
This is a very simplified example of what I really want to do, but if someone knows how I can get it to do what I want fairly simply, I would be very much appreciative.
To sum up, what I want is to have two sets of two bars. The first set with "True" under them and the second second set with "False" under them. I do not want to use numbers to represent the values, if possible as it will greatly complicate my more complex situation. But if I must, I would still like to know how to do it that way.
change the function getAxeMinMaxValues in orderBars.js
function getAxeMinMaxValues(series, AxeIdx) {
var minMaxValues = new Array();
for (var i = 0; i < series.length; i++) {
series[i].data[series[i].data.length - 1][AxeIdx];
minMaxValues[0] = 0;
minMaxValues[1] = series[i].data.length - 1;
}
return minMaxValues;
}
hope this will help

How do you switch the cursor to a pointer cursor when hovering over the bars in a Kendo UI bar chart

I have a Kendo UI Datavis Bar Chart for which I wish to show the pointer (hand) cursor when hovering over the bars in the chart and labels for those bars. When moving off the bars in the chart the cursor should return to the standard arrow pointer.
I noticed that the cursor turned into the text cursor when hovering over the axis labels (left, right, and bottom) and on the legend. So in addition to the above I would like the cursor to remain the standard cursor (arrow) when hovering over the axis labels and legend (since you cannot edit these). I would also like the cursor to switch to the pointer cursor when hovering over the x-axis (bottom) labels.
I can easily show a pointer cursor for the entire chart when hovering anywhere over the chart but that is not desired.
I have tried various strategies using the seriesHover event but so far nothing has worked.
How do I achieve the above?
Thomas your answer almost has me there. However, I need one additional piece of information:
How would I use the technique you show in your answer below within a CSS file. I have several Kendo UI charts some for which I need this behavior and some for which I do not. I have both ids and classes associated with the divs that contain the kendo UI charts (one div per chart). The actual charts are created using JavaScript code at load time. I tried to add the following, to the CSS within the CSS file but this had no effect:
#barChart {
/*cursor: pointer;*/
(svg > path):last-child {cusror: pointer;}
}
where #barChart is the Id of the div containing the KendoUI chart within the HTML
<div id="barChart" class="bargraph"></div>
Is there a way to do what you have shown below for charts that are created at load time within predefined divs? Does this have to be done by hooking into the charts hover event?
Just tried styling the Kendo UI bar chart demo with CSS; both turning the cursor into a hand and leaving it the default cursor on text works quite well. I just had to add two lines of CSS (and change the script/CSS URLs):
<html>
<head>
<title></title>
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script src="http://cdn.kendostatic.com/2012.3.1114/js/kendo.all.min.js"></script>
<link href="http://cdn.kendostatic.com/2012.3.1114/styles/kendo.common.min.css" rel="stylesheet" />
<link href="http://cdn.kendostatic.com/2012.3.1114/styles/kendo.default.min.css" rel="stylesheet" />
<style type="text/css">
/* When hovering over a bar, Kendo dynamically adds
a bar as the last child of the SVG element that
works as an overlay. So, effectively, we're
hovering over the last (dynamically added) child */
svg > path:last-child {cursor:pointer;}
svg {cursor:default}
</style>
</head>
<body>
<div id="example" class="k-content">
<div class="chart-wrapper">
<div id="chart" style="background: center no-repeat url('../../content/shared/styles/world-map.png');"></div>
</div>
<script>
function createChart() {
$("#chart").kendoChart({
theme: $(document).data("kendoSkin") || "default",
title: {
text: "Internet Users"
},
legend: {
position: "bottom"
},
chartArea: {
background: ""
},
seriesDefaults: {
type: "bar"
},
series: [{
name: "World",
data: [15.7, 16.7, 20, 23.5, 26.6]
}, {
name: "United States",
data: [67.96, 68.93, 75, 74, 78]
}],
valueAxis: {
labels: {
format: "{0}%"
}
},
categoryAxis: {
categories: [2005, 2006, 2007, 2008, 2009]
},
tooltip: {
visible: true,
format: "{0}%"
}
});
}
$(document).ready(function() {
setTimeout(function() {
// Initialize the chart with a delay to make sure
// the initial animation is visible
createChart();
$("#example").bind("kendo:skinChange", function(e) {
createChart();
});
}, 400);
});
</script>
</div>
<script type="text/javascript">
console.log("hi")
document.addEventListener("click",function(e){document.write(e.target)},false)
</script>
</body>
</html>​
If you have multiple charts and want this behavior only for some charts, I'd suggest using classes, like
<div id="barChart" class="bargraph cursorPointer"></div>
And change the CSS like
.cursorPointer svg > path:last-child {cursor:pointer;}
.cursorPointer svg {cursor:default}
(If you want the arrow cursor on text of all graphs, omit the .cursorPointer on the second line.)
If you want to change the cursor only in those labels where you have defined axisLabelClick event. You can do this:
var chart = $("#chart").data("kendoChart");
In my case, I just handle the first label, so I only want the pointer cursor in there:
var idLabel = chart._plotArea.axisY.children[0].options.id;
$('#' + idLabel).css('cursor', 'pointer');
Interestingly enough this worked for me perfectly (Only Bar Chart Kendo 2016):
svg > g g g g g g {cursor:pointer;}
svg {cursor:default}
Since this isn't a setting in Kendo yet, as #ThomasW, wrote you need to find a way to target the overlay path that gets shown when you hover over the graph elements.
In my case I noticed that all of those overlays have fill-opacity="0.2" and this did the trick:
.kendo-chart-wrapper [fill-opacity="0.2"] {
cursor: pointer;
}

Categories

Resources