I have a json code like this
[[1385420403000,9.86,6.91],[1385506802000,11.89,6.57],[1385593203000,14.11,10.58],[1385679602000,9.1,8.9],[1385766003000,13.59,7.53],[1385852402000,10.68,6.69],[1385938803000,11.03,10.52],[1386025202000,11.16,8.18],[1386111603000,12,5.76]]
I want to display the 3rd value (this.z) on tooltip with highstock.
This is my code to select data for the stacked column.
var date = [],
hp = [],
hc = [],
datalength = data.length;
for (i = 0; i < datalength; i ++) {
date.push([
data[i][0], // the date
]);
hp.push([
data[i][0], // the date
data[i][1], // hp
]);
hc.push ([
data[i][0], // the date
data[i][2], //hc
])
}
My tooltip :
tooltip: {
backgroundColor: 'rgba(0, 0, 0, 0.75)',
style: {
color: '#F0F0F0'
},
formatter: function() {return ' ' +
Highcharts.dateFormat('%A %d %b %Y', this.x) +""+'<br />'+
'HP : ' + this.y + " kwh"+'<br />' +
'Prix HP : ' + Highcharts.numberFormat((this.y*0.1467),2)+" €" +'<br />'+
'HC : ' + this.z + " kwh"+'<br />' +
'Prix HC: ' + Highcharts.numberFormat((this.z*0.1002),2)+" €"+'<br />' +
'Prix total : ' + Highcharts.numberFormat(((this.y*0.1467)+(this.z*0.1002)),2)+" €";
},
},
And the series :
series: [{
type: 'column',
name: 'HP',
data: hp,
},{
type: 'column',
name: 'HC',
data: hc,
}]
this.z is undefined. How can i replace it ?
To do this you would need to make a 3D set of data such that hp would look like:
{
type: 'column',
name: 'HP',
data: [
{x:1385420403000, y:9.86, note:6.91},
{x:1385506802000, y:11.89, note:6.57},
{x:1385593203000, y:14.11, note:10.58},
....
]
}
To do that you would set you hp filler loop to look something like:
hp.push([
data[i][0], // the date
data[i][1], // hp
data[i][2] // the note item.
]);
If you look at your hp.push code you have a dangling comma and you are never actually looking at the 3rd element in your array.
Then in your tooltip you would reference this.note.
Related
Hi I am trying to pass a variable to my tooltip using setData.
Here is a piece of my code explaining how I am setting the chart data, this code doesn't pass the sensorValue to my tooltip yet:
nitrogenDioxide = [];
$.each(data['NO2'], function(key, value) {
nitrogenDioxide.push([value.ts * 1000, value.rating]);
});
chart_2_1.series[0].setData(nitrogenDioxide);
chart_2_1.series[0].update({name:'Nitrogen Dioxide'}, true);
Here is the code I used to create my tooltip:
tooltip: {
shared: true,
useHTML: true,
formatter: function () {
var tooltipcontent = '<b>' + moment.unix((this.points[0].key / 1000)).format("DD/MM/YYYY HH:mm"); + '</b>';
tooltipcontent += '<table style="width:100%">';
$.each(this.points, function () {
console.log(this);
tooltipcontent += '<tr><td>' + this.y.toLocaleString() + '</td></tr>';
tooltipcontent += '<tr><td>' + sensorValue + '</td></tr>';
});
tooltipcontent += '</table>';
return tooltipcontent;
}
}
As you can see I have a variable called sensorValue in my tooltip. In the foreach loop I have a rating value (y-axis) and a sensor value. I want to pass that sensor value to me tooltip.
I have seen multiple ways of doing this online but none of them set the data the way I do, they do it like so:
new Highcharts.Chart( {
...,
series: [ {
name: 'Foo',
data: [
{
y : 3,
myData : 'firstPoint'
},
{
y : 7,
myData : 'secondPoint'
},
{
y : 1,
myData : 'thirdPoint'
}
]
} ]
} );
I have tried something like this but didn't know how to call this extra value in the tooltip:
nitrogenDioxide = [];
$.each(data['NO2'], function(key, value) {
nitrogenDioxide.push([value.ts * 1000, value.rating, value.value]);
});
In the above code I have pushed the sensor value into the nitrogenDioxide[] array.
I have tried my best to explain what I am trying to do, in my head the explanation makes sense but if it doesnt to you please let me know. Thank you in advance for any help.
I hope I understood correctly what is your issue and the demo posted below will be helpful for you.
When an array with an additional value is passed (sensorValue in your case) it can be retrieved inside formatter using this approach:
get hovered point index: this.point.index
use the point index to get additional value from this.series.userOptions.data array
Code:
Highcharts.chart('container', {
tooltip: {
formatter: function() {
var point = this.point,
series = this.series,
pointIndex = point.index,
text,
additionalValue;
text = '<span style="color:' +
this.color + '">\u25CF</span> ' +
series.name +
': <b>' +
this.y +
'</b><br/>';
additionalValue =
series.userOptions.data[pointIndex][2];
text += '<br> Additional value: ' +
additionalValue;
return text;
}
},
series: [{
data: [
[1, 2, 'aaa'], // 'aaa' is an additional value
[2, 5, 'bbb'],
[3, 9, 'ccc']
]
}],
});
Demo:
https://jsfiddle.net/BlackLabel/3g6om1fw/1/
I am using a highcharts to draw chart from HTML table , my problem is i want to custom the tooltip but the "this.x" or "this.key" returned as decimal number not as string, how can I get the x axis value as it is??
and that's my code:
Highcharts.chart('ChartContainer', {
data: {
table: 'tblData'
},
chart: {
type: 'line'
},
title: {
text: ''
},
yAxis: {
allowDecimals: false,
title: {
text: ''
}
},
tooltip: {
useHTML: true,
formatter: function () {
return GetCustomTooltip(this.series.name, this.y, firstSeriesToolTip, firstTooltipTitle, secondTooltipTitle, this.zvalue);
}
}
});
function GetCustomTooltip(xvalue, yvalue, TooltipArray, firstTooltipTitle, secondTooltipTitle, zvalue, thirdTooltipTitle) {
var tooltipMessage = '';
for (var i = 0; i < TooltipArray.length; i++) {
if (TooltipArray[i][0]== xvalue) {
tooltipMessage += '<b>' + xvalue + '</b><br>';
tooltipMessage += firstTooltipTitle + ': ' + '<b>' + yvalue + '</b><br>';
if (secondTooltipTitle != null)
tooltipMessage += secondTooltipTitle + ': ' + '<b>' + TooltipArray[i][1] + '</b><br>';
if (thirdTooltipTitle != null)
tooltipMessage += thirdTooltipTitle + ': ' + '<b>' + TooltipArray[i][3] + '</b><br>';
break;
}
}
return tooltipMessage;
}
and the table I build it dynamically before draw the chart.
I got the right values when I change the xAxis type to category
I have a Pie chart with multiple rings and created a Custom Legend function with below code:
var data = [{
labels: ["Mumbai", "Chennai", "Hyderabad", "Bangalore"],
data: [30, 32, 38, 50],
backgroundColor: [
"#4b77a9",
"#5f255f",
"#d21243",
"#B27200"
],
borderColor: "#fff"
}, {
labels: ["India 2018", "India 2017"],
data: [450, 400],
backgroundColor: [
"#92d400",
"#95a455"
],
borderColor: "#fff"
}];
The first ring represents four individual cities and center rings represents Country total value, but not the sum total of four cities.
I want to show this custom legend:
Mumbai: 30
Chennai: 32
Hyderabad: 38
Bangalore: 50
India: 450
Rest of Mumbai: 420
Rest of Chennai: 418
Rest of Hyderabad: 412
Rest of Bangalore: 400
First set is individual data values.
Second set is (India value - City value)
Below is the custom legend function:
legendCallback: function (chart) {
var text = [];
text.push('<ul class="list-inline my-0 text-center ' + chart.id + '-legend text-secondary">');
for (var i = 0; i < chart.data.datasets[0].data.length; i++) {
text.push('<li class="list-inline-item"><i class="fas fa-circle pr-1" style="color:' +
chart.data.datasets[0].backgroundColor[i] + '"></i>');
if (chart.data.datasets[0].labels[i]) {
text.push('<span class="font-weight-bold">' + chart.data.datasets[0].labels[i] + ': ' + chart.data.datasets[0].data[i] +'</span>');
}
text.push('</li>');
}
text.push('</ul>');
text.push('</ul>');
text.push('<ul class="list-inline">');
text.push('<li class="list-inline-item">Rest of Mumbai: 420</li>');
text.push('<li class="list-inline-item">Rest of Chennai: 418</li>');
text.push('<li class="list-inline-item">Rest of Hyderabad: 412</li>');
text.push('<li class="list-inline-item">Rest of Bangalore: 400</li>');
text.push('</ul>');
return text.join('');
},
I am able to show individual label values but not the Rest of the *** labels value.
Here is the JSFiddle (https://jsfiddle.net/kingBethal/aubsjn4c/11/)
Update# 1
Below is the table represents the values in the Pie and desired Custom legend output:
Custom legend will show (India 2018 minus individual city) values.
An example:
Rest of Mumbai = India 2018 (450) - Mumbai (30) = 420
just need to reference the second dataset and subtract the city values...
here, you're building the first legend...
for (var i = 0; i < chart.data.datasets[0].data.length; i++) {
text.push('<li class="list-inline-item"><i class="fas fa-circle pr-1" style="color:' + chart.data.datasets[0].backgroundColor[i] + '"></i>');
if (chart.data.datasets[0].labels[i]) {
text.push('<span class="font-weight-bold">' + chart.data.datasets[0].labels[i] + ': ' + chart.data.datasets[0].data[i] +'</span>');
}
text.push('</li>');
}
to build the second, use the same code, but reference the second dataset and subtract the city value...
for (var i = 0; i < chart.data.datasets[0].data.length; i++) {
text.push('<li class="list-inline-item"><i class="fas fa-circle pr-1" style="color:' + chart.data.datasets[0].backgroundColor[i] + '"></i>');
if (chart.data.datasets[0].labels[i]) {
text.push('<span class="font-weight-bold">Rest of ' + chart.data.datasets[0].labels[i] + ': ' +
(chart.data.datasets[1].data[0] - chart.data.datasets[0].data[i]) + // <-- second dataset = datasets[1] and india 2018 = data[0]
'</span>');
}
text.push('</li>');
}
see following working snippet...
var data = [{
labels: ["Mumbai", "Chennai", "Hyderabad", "Bangalore"],
data: [30, 32, 38, 50],
backgroundColor: [
"#4b77a9",
"#5f255f",
"#d21243",
"#B27200"
],
borderColor: "#fff"
}, {
labels: ["India 2018", "India 2017"],
data: [450, 400],
backgroundColor: [
"#92d400",
"#95a455"
],
borderColor: "#fff"
}];
var options = {
cutoutPercentage: 35,
legendCallback: function (chart) {
var text = [];
text.push('<ul class="list-inline my-0 text-center ' + chart.id + '-legend text-secondary">');
for (var i = 0; i < chart.data.datasets[0].data.length; i++) {
text.push('<li class="list-inline-item"><i class="fas fa-circle pr-1" style="color:' + chart.data.datasets[0].backgroundColor[i] + '"></i>');
if (chart.data.datasets[0].labels[i]) {
text.push('<span class="font-weight-bold">' + chart.data.datasets[0].labels[i] + ': ' + chart.data.datasets[0].data[i] +'</span>');
}
text.push('</li>');
}
for (var i = 0; i < chart.data.datasets[0].data.length; i++) {
text.push('<li class="list-inline-item"><i class="fas fa-circle pr-1" style="color:' + chart.data.datasets[0].backgroundColor[i] + '"></i>');
if (chart.data.datasets[0].labels[i]) {
text.push('<span class="font-weight-bold">Rest of ' + chart.data.datasets[0].labels[i] + ': ' +
(chart.data.datasets[1].data[0] - chart.data.datasets[0].data[i]) + // <-- second dataset = datasets[1] and india 2018 = data[0]
'</span>');
}
text.push('</li>');
}
text.push('</ul>');
return text.join('');
},
legend: {
display: false
},
plugins: {
datalabels: {
color: '#ffffff'
}
},
tooltips: {
callbacks: {
label: function (item, data) {
var label = data.datasets[item.datasetIndex].labels[item.index];
var value = data.datasets[item.datasetIndex].data[item.index];
var allData = data.datasets[item.datasetIndex].data;
var tooltipData = allData[item.index];
return label + ': ' + tooltipData;
}
},
titleFontSize: 14,
bodyFontSize: 12
}
};
var ctx = document.getElementById("my-chart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'pie',
data: {
datasets: data
},
options: options
});
$('#legend').html(myChart.generateLegend());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<canvas id="my-chart"></canvas>
<div id="legend"></div>
I'm trying to edit the tooltip in a c3 line-chart. Specifically, I need to access the current x-value within the chart.tooltip.format.value function. However, the function is not passed the x-value explicitly.
var chart = c3.generate({
tooltip: {
format: {
value: function (value, ratio, id, index) {
return value;
}
}
},
data: {
x: 'YEAR',
xFormat: '%Y',
url: myURL',
},
axis: {
x: {
type: 'timeseries',
tick: {
format: '%Y'
}
},
},
});
You can use the tooltip's contents property to create a custom tooltip, and in there you can access the X value via: d[0].x.
Edit: use d[0].x.getFullYear() to retrieve only the year part of the date (it's a time series so C3 internally stores the supplied year as a javascript date object)
Here's code I've taken from this discussion https://github.com/c3js/c3/issues/444, and modified:
function tooltip_contents(d, defaultTitleFormat, defaultValueFormat, color) {
var $$ = this, config = $$.config, CLASS = $$.CLASS,
titleFormat = config.tooltip_format_title || defaultTitleFormat,
nameFormat = config.tooltip_format_name || function (name) { return name; },
valueFormat = config.tooltip_format_value || defaultValueFormat,
text, i, title, value, name, bgcolor;
// You can access all of data like this:
//console.log($$.data.targets);
for (i = 0; i < d.length; i++) {
if (! (d[i] && (d[i].value || d[i].value === 0))) { continue; }
// to exclude
//if (d[i].name === 'data2') { continue; }
if (! text) {
title = 'MY TOOLTIP # ' + d[0].x.getFullYear(); // SHOW X-VALUE, year only (given it is a time series)
text = "<table class='" + CLASS.tooltip + "'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + "</th></tr>" : "");
}
name = nameFormat(d[i].name);
value = valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index);
bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id);
text += "<tr class='" + CLASS.tooltipName + "-" + d[i].id + "'>";
text += "<td class='name'><span style='background-color:" + bgcolor + "'></span>" + name + "</td>";
text += "<td class='value'>" + value + "</td>";
text += "</tr>";
}
return text + "</table>";
}
var chart = c3.generate({
data: {
x: 'year',
xFormat: '%Y',
columns: [
['year', '1970', '1975', '1980', '1985', '1990'],
['data1', 100, 200, 150, 300, 200],
['data2', 400, 500, 250, 700, 300],
]
},
axis: {
x: {
type: 'timeseries',
tick: {
format: '%Y'
}
},
},
tooltip: {
contents: tooltip_contents
}
});
My fiddle, showing the current x-value: http://jsfiddle.net/w7h385h3/5/
The legend in my highcharts is not functioning correctly. I have 2 series, each named differently. When I click on 'series1' on the legend, the data for 'series1' is hidden leaving 'series2' behind. However, when I click on 'series2' first, all the data is hidden instead of only 'series2'. What are some common mistakes that could lead to this? Here is a snippet of the involved code:
EDIT: Here is a jsFiddle reproduction of my bug. You can see when you click on "Pool" in the legend both series are removed. Clicking on client, however, works as expected. https://jsfiddle.net/LLExL/5616/
EDIT2: I found the solution. Apparently if the first index of a given series of data is empty, the error occurs. It also appears that it must have the same number of elements equal to the index with the least amount of data points. So in my case, I check if the first element in clientChartData or poolChartData is empty, if so I append 5 pairs of quotes to that array.
$('#all-cpus').highcharts({
chart: {
type: 'boxplot',
inverted: true
},
title: {
text: 'All CPUs'
},
xAxis: {
title: { text: 'Hybrids' }
},
yAxis: {
title: { text: 'Yield' }
},
legend: { enabled: true },
credits: { enabled: false },
tooltip: {},
plotOptions: {
boxplot: {
fillColor: '#6c3a38',
lineWidth: 3,
medianWidth: 3,
stemColor: '#DF5353',
stemDashStyle: 'dot',
stemWidth: 1,
whiskerColor: '#AAEEEE',
whiskerLength: '20%',
whiskerWidth: 3
}
},
series: [
{ name: 'Client' },
{ name: 'Pool' }
]
});
Here is where I set the chart data. Assume organizedClientData as all the data I need.
//Set the data to be displayed on the chart
clientChartData = organizedClientData;
$chart.highcharts().series[0].setData(clientChartData, false);
$chart.highcharts().series[0].update({name: this.clientData.name}, false);
$chart.highcharts().series[1].setData(poolChartData, false);
$chart.highcharts().series[1].update({name: this.poolData.name}, false);
//Set tooltip info to reflect dynamic data and to include acres
$chart.highcharts().tooltip.options.formatter = function() {
var index = this.point.x;
var numAcresPool = poolAcres[ index ];
var numAcresClient = clientAcres[ index ];
var tooltipString = this.point.category + '<br>' +
this.point.series.name + '<br>' +
'Max: ' + this.point.high + '<br>' +
'Upper Quartile: ' + this.point.q3 + '<br>' +
'Median: ' + this.point.median + '<br>' +
'Lower Quartile: ' + this.point.q1 + '<br>' +
'Min: ' + this.point.low + '<br>';
//Handle client vs. pool acreage display, and check if on the 'All Cpus' tab
if(this.point.series.name == 'Pool') {
tooltipString = tooltipString + 'Acres: ' + numAcresPool;
}
else if(this.point.series.name == 'All Farms' /*&& $chart.selector != '#all-cpus'*/) {
tooltipString = tooltipString + 'Acres: ' + numAcresClient;
}
return tooltipString;
};
var xaxis = $chart.highcharts().xAxis[0];
var title = { text: this.getProfileData().cropId == 1 ? 'Hybrids' : 'Varieties' };
xaxis.setCategories(categories, true);
xaxis.setTitle(title, true);
$chart.highcharts().setSize( $chart.parent().width() - 15, $chart.highcharts().xAxis[0].categories.length * 50 + 150 );
$chart.highcharts().redraw();
This looks like a bug, I reported that to our developers here: https://github.com/highcharts/highcharts/issues/4939