chart js tooltip how to control the data that show - javascript

I'm using chart.js plugin and using a group chart by bar view.
when i hover a group of bars i can see a tooltip that show me the data of this bars.
but i what to change the tooltip to show my only single data when I'll hover the bar data.
and I what to show diffrent data info.
jsfiddle example
var ctx = document.getElementById("errorChart").getContext("2d");
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.5)",
strokeColor: "rgba(220,220,220,0.8)",
highlightFill: "rgba(220,220,220,0.75)",
highlightStroke: "rgba(220,220,220,1)",
data: [65, 0, 0, 0, 0, 0, 0]
},
{
label: "My Second dataset",
fillColor: "rgba(151,187,205,0.5)",
strokeColor: "rgba(151,187,205,0.8)",
highlightFill: "rgba(151,187,205,0.75)",
highlightStroke: "rgba(151,187,205,1)",
data: [28, 48, 40, 19, 86, 27, 90]
}
]
};
var myBarChart = new Chart(ctx).Bar(data);

You could extend the bar graph to include this functionality. By default it will return both bars at the index you have hovered over, it will also check for multiple bars at the area you hovered before creating the tooltip and put any extras in that were missing.
So to do this you will need to override two functions getBarsAtEvent and showToolTip here is an example and fiddle
I have tried to make it clear the two important areas that have changed look at the comments in the extended bar type. Small changes were also made to any reference of the helpers as before they were within the scope but now they need to explicitly call Chart.helpers
Chart.types.Bar.extend({
name: "BarOneTip",
initialize: function(data){
Chart.types.Bar.prototype.initialize.apply(this, arguments);
},
getBarsAtEvent : function(e){
var barsArray = [],
eventPosition = Chart.helpers.getRelativePosition(e),
datasetIterator = function(dataset){
barsArray.push(dataset.bars[barIndex]);
},
barIndex;
for (var datasetIndex = 0; datasetIndex < this.datasets.length; datasetIndex++) {
for (barIndex = 0; barIndex < this.datasets[datasetIndex].bars.length; barIndex++) {
if (this.datasets[datasetIndex].bars[barIndex].inRange(eventPosition.x,eventPosition.y)){
//change here to only return the intrested bar not the group
barsArray.push(this.datasets[datasetIndex].bars[barIndex]);
return barsArray;
}
}
}
return barsArray;
},
showTooltip : function(ChartElements, forceRedraw){
console.log(ChartElements);
// Only redraw the chart if we've actually changed what we're hovering on.
if (typeof this.activeElements === 'undefined') this.activeElements = [];
var isChanged = (function(Elements){
var changed = false;
if (Elements.length !== this.activeElements.length){
changed = true;
return changed;
}
Chart.helpers.each(Elements, function(element, index){
if (element !== this.activeElements[index]){
changed = true;
}
}, this);
return changed;
}).call(this, ChartElements);
if (!isChanged && !forceRedraw){
return;
}
else{
this.activeElements = ChartElements;
}
this.draw();
console.log(this)
if (ChartElements.length > 0){
//removed the check for multiple bars at the index now just want one
Chart.helpers.each(ChartElements, function(Element) {
var tooltipPosition = Element.tooltipPosition();
new Chart.Tooltip({
x: Math.round(tooltipPosition.x),
y: Math.round(tooltipPosition.y),
xPadding: this.options.tooltipXPadding,
yPadding: this.options.tooltipYPadding,
fillColor: this.options.tooltipFillColor,
textColor: this.options.tooltipFontColor,
fontFamily: this.options.tooltipFontFamily,
fontStyle: this.options.tooltipFontStyle,
fontSize: this.options.tooltipFontSize,
caretHeight: this.options.tooltipCaretSize,
cornerRadius: this.options.tooltipCornerRadius,
text: Chart.helpers.template(this.options.tooltipTemplate, Element),
chart: this.chart
}).draw();
}, this);
}
return this;
}
});
then to use it just do what you did before but use BarOneTip (call it whatever you like, what ever is in the name attribute of the extended chart will be available to you.
var ctx = document.getElementById("errorChart").getContext("2d");
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.5)",
strokeColor: "rgba(220,220,220,0.8)",
highlightFill: "rgba(220,220,220,0.75)",
highlightStroke: "rgba(220,220,220,1)",
data: [65, 0, 0, 0, 0, 0, 0]
},
{
label: "My Second dataset",
fillColor: "rgba(151,187,205,0.5)",
strokeColor: "rgba(151,187,205,0.8)",
highlightFill: "rgba(151,187,205,0.75)",
highlightStroke: "rgba(151,187,205,1)",
data: [28, 48, 40, 19, 86, 27, 90]
}
]
};
var myBarChart = new Chart(ctx).BarOneTip(data);
I should mention that if chartjs gets updated you would need to manually put any changes to the functions into the overridden ones

Related

.datasets is undefined when trying to access bars from chart.js

I'm trying to recreate this example:
chart.js bar chart color change based on value
With the following code
<script src="/chart.js/dist/Chart.js"></script>
<canvas id="myChart" width="400" height="400"></canvas>
<script>
var ctx = document.getElementById('myChart').getContext('2d');
window.myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 3, 3],
fillColor: "rgba(220,220,220,0.5)",
strokeColor: "rgba(220,220,220,0.8)",
highlightFill: "rgba(220,220,220,0.75)",
highlightStroke: "rgba(220,220,220,1)",
borderWidth: 1
}]
},
});
var bars = myChart.datasets[0].bars;
for (i = 0; i < bars.length; i++) {
var color = "green";
//You can check for bars[i].value and put your conditions here
if (bars[i].value < 3) {
color = "red";
} else if (bars[i].value < 5) {
color = "orange"
} else if (bars[i].value < 8) {
color = "yellow"
} else {
color = "green"
}
bars[i].fillColor = color;
}
myChart.update();
</script>
but I get in console the TypeError:
myChart.datasets is undefined on the line var bars = myChart.datasets[0].bars;
Do you have an idea what I'm overlooking?
Thank you
Here is the complete example you want.
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<canvas id="myChart" width="400" height="400"></canvas>
<script>
//Creating a barchart with default values
var myChart = new Chart(document.getElementById("myChart"), {
"type": "bar",
"data": {
"labels": ["January", "February", "March", "April", "May", "June", "July"],
"datasets": [{
"label": "My First Dataset",
"data": [65, 59, 80, 81, 56, 55, 40],
"fill": false,
"backgroundColor": ["#fb4d4d", "#fb9d4d", "#f8fb4d", "#98fb4d", "#4effee", "#4cb9f8", "#574cf8"],
"borderColor": ["#fb4d4d", "#fb9d4d", "#f8fb4d", "#98fb4d", "#4effee", "#4cb9f8", "#574cf8"],
"borderWidth": 1
}]
},
"options": {
"scales": {
"yAxes": [{
"ticks": {
"beginAtZero": true
}
}]
}
}
});
//Getting the bar-chart existing values
var bars = myChart.config.data.datasets[0];
var data = bars.data;
//Updating the existing value (object which holds value)
for (i = 0; i < data.length; i++) {
var bgcolor = "";
var brcolor = "";
if (data[i] < 30) {
bgcolor = "red";
brcolor = "red";
} else if (data[i] < 50) {
bgcolor = "orange";
brcolor = "orange";
} else if (data[i] < 80) {
bgcolor = "yellow";
brcolor = "yellow";
} else {
bgcolor = "green";
brcolor = "green";
}
bars.backgroundColor[i] = bgcolor;
bars.borderColor[i] = brcolor;
}
//Triggering the chart update in 3 seconds.
setTimeout(function(){
myChart.update();
}, 3000);
</script>
your dataset was empty, was not being done as the example quoted
The correct way to do as the example you mentioned is:
var barChartData = {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [
{
label: '# of Votes',
data: [12, 19, 3, 5, 3, 3],
fillColor: "rgba(220,220,220,0.5)",
strokeColor: "rgba(220,220,220,0.8)",
highlightFill: "rgba(220,220,220,0.75)",
highlightStroke: "rgba(220,220,220,1)",
borderWidth: 1
}
]
};
var ctx = document.getElementById('myChart').getContext('2d');
window.myObjBar = new Chart(ctx).Bar(barChartData, {
responsive : true
});
var bars = myObjBar.datasets[0].bars;
for(i=0;i<bars.length;i++){
var color="green";
//You can check for bars[i].value and put your conditions here
if(bars[i].value<3){
color="red";
}
else if(bars[i].value<5){
color="orange"
}
else if(bars[i].value<8){
color="yellow"
}
else{
color="green"
}
bars[i].fillColor = color;
}
myObjBar.update(); //update the cahrt
Here is an example working :)

Javascript window.onload not displaying charts with Chart.js and Flask

I'm new to Javascript and now I'm tasked to display charts with Chart.js. I did grouping in Python and used Flask to build the web app. However, my chart is somehow not displayed and I'm not sure why.
HTML
<canvas id="barchart2" width="600" height="400"></canvas>
JS
<script>
var config = {
type: 'bar',
labels : [
"52",
"51",
"54",
"53",
"46",
"82",
"57",
"48",
"50",
"56",
],
datasets : [
{
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
data : [
611,
18,
11,
10,
9,
8,
6,
3,
2,
2,
]
}
]
},
options: {
legend: {
display: true,
},
title: {
display: true,
text: 'Top 10 District in Singapore',
}
},
};
window.onload = function() {
var ctx = document.getElementById("barchart2").getContext("2d");
window.myBar = new Chart(ctx, config);
};
</script>
When I used this JS instead
var barData = {
labels : [{% for item in lbl1 %}
"{{item}}",
{% endfor %}],
datasets : [
{
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
data : [{% for item in val1 %}
{{item}},
{% endfor %}]
}
]
}
// get bar chart canvas
var mychart = document.getElementById("barchart2").getContext("2d");
// draw bar chart
new Chart(mychart).Bar(barData);
It worked perfectly (note: without options. I tried to add options, but the options doesn't show although the charts still appears. That's why I wanna change to this format instead).
But when I use the window.onload function, the chart doesn't appear at all.
Would appreciate your help. Thanks!
Could you paste here the complete generated JS code with the data? Or review your data, because I think that might be the problem somehow.
Here's a JSFiddle with your original code (sans your data) that works:
https://jsfiddle.net/wj80597q/5/
var config = {
type: 'bar',
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
data: [0, 10, 5, 2, 20, 30, 45]
}]
},
options: {
legend: {
display: true,
},
title: {
display: true,
text: 'Top 10 District in Singapore',
}
},
};
(function() {
var ctx = document.getElementById("barchart2").getContext("2d");
window.myBar = new Chart(ctx, config);
})()

I don't want to auto reflect chart with $watch in angulars js?

Right now I am implementing line chart in angular js. And I have written one directive for this, So it is working fine, But when I am putted $watch in this directive then every time chart will updating continuously. I want to use $watch for some dynamic change after loaded the page.
angular.module('app.abc').directive('linechart', function () {
return {
restrict: 'A',
template:'',
link: function (scope, element, attributes) {
scope.$watch(function(){
var lineOptions = {
scaleShowGridLines : true,
scaleGridLineColor : "rgba(0,0,0,.05)",
scaleGridLineWidth : 1,
bezierCurve : true,
};
var lineData = { labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My Second dataset",
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(151,187,205,1)",
data: [28, 48, 40, 19, 86, 27, 90]
}
]
};
var ctx = element[0].getContext("2d");
var myNewChart = new Chart(ctx).Line(lineData, lineOptions);
})
}
}
});
<canvas style="display: block;" linechart height="120" ></canvas>
Line chart reflecting updates is contiguously. But I don't want to reflection continuously. I have tried to put my ctx object outside of $watch, but chart is not showing anything. Actually I am new in angular js and also new in directives. Please give me idea how handle this directive with $watch. I have seen one demo(based on javascript) example https://codepen.io/SitePoint/pen/mJRrKw

How to draw the X-axis (line at Y = 0) in Chart.js?

I want to draw the X-axis, i.e. a horizontal line at Y = 0, to better see where the positive and negative values of Y are.
I want something like this:
Is this possible in Chart.js
EDIT 1
I want to draw the line in the Chart object, so being able to interact with it. For example: points over the X-axis could be drawn green and points under it could be red.
You can Use :
scales: {
xAxes: [{
gridLines: {
zeroLineWidth: 3,
zeroLineColor: "#2C292E",
},
}]
}
Blockquote
You can extend the chart to do both - draw the line and color the points
Chart.types.Line.extend({
name: "LineAlt",
initialize: function (data) {
Chart.types.Line.prototype.initialize.apply(this, arguments);
this.datasets.forEach(function (dataset, i) {
dataset.points.forEach(function (point) {
// color points depending on value
if (point.value < 0) {
// we set the colors from the data argument
point.fillColor = data.datasets[i].pointColor[0];
} else {
point.fillColor = data.datasets[i].pointColor[1];
}
// we need this so that the points internal color is also updated - otherwise our set colors will disappear after a tooltip hover
point.save();
})
})
},
draw: function () {
Chart.types.Line.prototype.draw.apply(this, arguments);
// draw y = 0 line
var ctx = this.chart.ctx;
var scale = this.scale;
ctx.save();
ctx.strokeStyle = '#ff0000';
ctx.beginPath();
ctx.moveTo(Math.round(scale.xScalePaddingLeft), scale.calculateY(0));
ctx.lineTo(scale.width, scale.calculateY(0));
ctx.stroke();
ctx.restore();
}
});
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
// point color is a an array instead of a string
pointColor: ["rgba(220,0,0,1)", "rgba(0,220,0,1)"],
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 81, -56, -55, 40]
}
]
};
var ctx = document.getElementById("myChart").getContext("2d");
// use our new chart type LineAlt
var myNewChart = new Chart(ctx).LineAlt(data);
Fiddle - http://jsfiddle.net/mbddzwxL/

How in javascript string convert in code?

I have some trouble;
I want to change code
in row labels (this is parameters of chart.js)
but my labels change and i want to set this parameter
Example
From this
var nData = {
labels: [1,2,3,4,5,6,7,8]
}
to
var nData = {
labels: [**"1,2,3,4,5,6,7,8,9"**]
}
From
var nData = {
labels: [1,2,3,4,5,6,7,8],
datasets: [
{
fillColor: "rgba(220,220,220,0)",
strokeColor: "rgba(220,220,220,1)",
highlightFill: "rgba(220,220,220,0.75)",
highlightStroke: "rgba(220,0,220,1)",
data: [array[0].amount, array[1].amount, array[2].amount, array[3].amount, array[4].amount, array[5].amount, array[6].amount,array[7].amount],
title : "My revenue"
}
]
};
var opts = {
scaleLineColor: "gray",
}
var ctx = document.getElementById("canvas").getContext("2d");
window = new Chart(ctx).Line(nData,opts);
}
like this,
but this variant is not work.
var a="1,2,3,4,5,6,7,8";
var nData = {
labels: [eval(a)],
datasets: [
{
fillColor: "rgba(220,220,220,0)",
strokeColor: "rgba(220,220,220,1)",
highlightFill: "rgba(220,220,220,0.75)",
highlightStroke: "rgba(220,0,220,1)",
data: [array[0].amount, array[1].amount, array[2].amount, array[3].amount, array[4].amount, array[5].amount, array[6].amount,array[7].amount],
title : "My revenue"
}
]
};
var opts = {
scaleLineColor: "gray",
}
var ctx = document.getElementById("canvas").getContext("2d");
window = new Chart(ctx).Line(nData,opts);
}
If I understand you correctly it's just:
nData.labels = [nData.labels.join()];
It's equivalent to
nData.labels = [nData.labels.join(',')];
because the default value for join is a comma.
A third option is to do
nData.labels = [nData.labels.toString()];
Which in this case also will return the desired result.

Categories