Good morning. I'm working with Chart.js and have it set up to produce a nice bar chart. Unfortunately, the default popup when you hover over the bars only shows the color of the bar and it's value. The color of the bar is unhelpful to our users. I would like the popup to display the label of each bar in the group and its value. Sort of like:
First Project : 80
Second project : 25
Third project : 64
There have been other posts about this issue and they recommended using
multiTooltipTemplate : "<%%=datasetLabel%> : <%%=value%>"
I tried it but it had no effect. No errors but no change to the popup. Perhaps it isn't set up correctly. Any suggestions?
$.post(url, dataObject)
.done(function (results) {
if (results.length > 0) {
//Build mydatasets empty array
var mydatasets = [];
//Loop through the results and build a new data array object to be added to the master data array object that will
//be assigned to the chart bars.
for (var i = 0; i < results.length; i++) {
var dataset =
{
label : results[i].WorkTypeName,
fillColor : getRandomColor(), //Found in the ChartHelpers.js file
data : results[i].Hours
}
mydatasets.push(dataset);
}
//Plug the data into the data structure
var data = {
labels: startdates,
datasets: mydatasets
};
//Get chart context
var ctx = $("#myChart").get(0).getContext("2d");
// This will get the first returned node in the jQuery collection and use it to create a bar chart
myBarChart = new Chart(ctx, {
options: {
multiTooltipTemplate : "<%%=datasetLabel%> : <%%=value%>"
}
}).Bar(data);
}
});
Found the answer with some additional experimentation! Other forum posts had suggested using
multiTooltipTemplate : "<%%=datasetLabel%> : <%%=value%>"
in the options. that generated a syntax error message. Removing the extra two percent signs caused the popup to display as planned.
multiTooltipTemplate : "<%=datasetLabel%> : <%=value%>"
Related
I am using the Highcharts synchronized charts to display three different variables. However, in order to render cleaner graphs, I'd like to display the x-axis (which is the same for all three graphs) only for the bottom graph.
For that, I presume, I need to cycle at the end of the generation process through the charts and suppress the first two x-axis, kind like
for (i = 0; i < (Highcharts.charts.length - 1); i = i + 1)
{
chart = Highcharts.charts[i];
chart.xAxis.labels.enabled = false;
}
Here is the default fiddle.
I don't succeed in getting this to work. Can anyone help me out on this?
You can set the xAxis.visible property depending on the chart index:
success: function (activity) {
activity = JSON.parse(activity);
activity.datasets.forEach(function (dataset, i) {
...
Highcharts.chart(chartDiv, {
xAxis: {
visible: i === 2,
...
},
...
});
});
}
Live demo: https://jsfiddle.net/BlackLabel/cmdb5at0/
API Reference: https://api.highcharts.com/highcharts/xAxis.visible
What i am trying to do is i want to display a chart based on my dynamic data i used Angular ForEach to loop through all my objects array see my code below:
var parse = JSON.parse(jsondata);
angular.forEach(parse, function (value, key) {
var dataSet = anychart.data.set(value);
var chart = anychart.column();
var series = chart.column(value);
chart.title("Data Sets: Array of Objects");
chart.container("container");
chart.draw();
});
it correctly display the count of my chart but the data of each object array is not showing up see picture below
but if put a static data like this :
var data = [
{x:"January", value: 12000},
{x:"February", value: 15000},
{x:"March", value: 16000},
{x:"April", value: 14000},
{x:"May", value: 10000}
];
the chart displays correctly.
can anyone help me with this ? any help will greatly appreciated.
Everything depends on the value content inside the loop. You are applying the value to the series and dataSet as well.
If you are using dataSet, you should apply the value to the dataSet, map the data, then apply the mapping to the series. Like this:
var dataSet = anychart.data.set(value);
var mapping = dataSet.mapAs({'x': 0, 'value': 1}); // for example
var chart = anychart.column();
var series = chart.column(dataSet);
The mapping depends on your data. If the value includes ready-to-use data that matches the default mapping you can apply it directly to the series.
Can you share the value content?
The chart can work with dynamic data. All you need is to apply new data to the existing dataSet, like this:
dataSet.data(newData);
And that's it! There's no need to recreate chart/series/dataSet.
I have been playing a lot with Chart.Js but trying my hardest to avoid getting into Canvas itself due to time constraints and a personal preference of the SVG route of D3 et al.
I have a mixture of charts on a dashboard page, and everything looks fantastic except for one issue - you have to hover over a pie segment in order to see the underlying % or value.
For a dashboard view, my users would prefer to just quickly see some data labels on the segments - as with Excel - possibly easier to explain with an image:
https://support.office.com/en-gb/article/Display-or-hide-data-label-leader-lines-in-a-pie-chart-d7e7c62e-aaa5-483a-aa00-6d2c437df61b
The problem with other solutions I've found here are that they are simply displaying the value in the segment, but some segments are too small for this to be the way forward.
There were also other solutions that always displayed tooltips - but there was a lot of overlapping and generally looked quite horrible.
I would even be happy if the legend could display data next to it, but I don't understand why a lot more people haven't requested the same functionality - am I missing something?
This feature isn't available so far, so there is no really quick solution for that.
It actually is possible to show the data within the legend (I have done this for dashboards I create at work). You just need to use the generateLabels legend label property to achieve this.
Here is an example that shows the data value in parenthesis within the legend (this is done in the legend item text property that is returned from the function).
generateLabels: function(chart) {
var data = chart.data;
if (data.labels.length && data.datasets.length) {
return data.labels.map(function(label, i) {
var meta = chart.getDatasetMeta(0);
var ds = data.datasets[0];
var arc = meta.data[i];
var custom = arc.custom || {};
var getValueAtIndexOrDefault = Chart.helpers.getValueAtIndexOrDefault;
var arcOpts = chart.options.elements.arc;
var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
return {
// here is where we are adding the data values to the legend title
text: label + " (" + ds.data[i].toLocaleString() + ")",
fillStyle: fill,
strokeStyle: stroke,
lineWidth: bw,
hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
index: i // extra data used for toggling the correct item
};
});
} else {
return [];
}
}
You can see it in action at this codepen.
I'm trying for days now to get Highstock working with an external CSV file. The issue was first that the imported file was sorted in "descending" order whereas Highcharts requires the data to be sorted in "ascending" order. Once I found a JSFiddle/Codepen close to my problem, I managed to display the data correctly.
Now the problem is that on the x-axis the dates are displayed as something like 00:00:00.500 whereas it should be looking like this 2016-03-11.
I have created a codepen since it may be easier for you to respond to it than copy/pasting here a lot of code: http://codepen.io/bauhausweb/pen/aNpbxg
Thanks for looking into my issue!
For your example, there seems to at least be the problem of 2016-03-11 simply being a string and not a timestamp in milliseconds, which causes it to chose the defaults of 0, 1, 2, ... as x-values instead.
Below I've provided an example of how you can use the data modules csv attribute to achieve a similar result, with the help of the complete function:
$(function () {
$.get("https://www.example.com/my.csv", function (csv) {
$('#container').highcharts('StockChart', {
data: {
complete: function(o) {
o.series[0].data.reverse();
},
csv: csv
}
});
});
});
Or look at this JSFiddle demonstration.
Try to do something like this:
$.each(lines, function (lineNo, line) {
if (lineNo > 0 && lineNo < 557) {
var items = line.split(',');
// var seriesname = String(items[0]); // this is the area name
var seriesname = "Gold"; // this is the area name
var price = parseFloat(items[1]);
var f_date = items[0];
var format = String(f_date.replace(/-/g,','));
var date_items = format.split(',');
var d = Date.UTC(date_items[0],date_items[1],date_items[2]);
console.log(d);
var date = d;
// this will be the id of the drilldown
// var shift_one_value = parseFloat(items[3]); // drilldown shift1 value
// var shift_two_value = parseFloat(items[4]); // drilldown shift2 value
series.data.push({
name: seriesname,
y: price,
x: date
});
}
});
The problem is the date it would be formated in UTC
Your code has a lot of oddities. Your xAxis is set to datetime which is good. With a point interval of one day - also good. But, if you look at your series.data you are sending in data formatted like:
{
name: "Gold",
x: "1233.6",
y: 1233.6
}
You are setting the y here:
var date = String(items[1]);
You should be using items[0]. Now, you also have to parse this string into javascript time. Something like this can work:
var arr = String(items[0]).split("-");
var date = Date.UTC(arr[0], arr[1], arr[2]);
However, now your chart throws error that date is not sorted. See updated pen here.
I am currently using Highcharts in my website. In one of my charts (a Basic Column chart) I have multiple series, which I can click on the name displayed on the bottom to show/hide.
I can have a lot of series and I would like to limit the number of series to 3 at the same time. It means when it loads the graph, it shows only 3 series and the others are not shown. If I click on a 4th serie, one of the 3 originally present will disappear, so that the number of active serie always remain 3.
I've been looking for it and I found out I needed to do some modifications in the plotOptions.series field and I digged into the Highcharts API reference but didn't found what I wanted. My first attempt at the code would be something like this :
$('#container').highcharts({
plotOptions:{
series: {
var series = this.series;
var nb_of_visible_series = 0;
//Here i count the number of visible series
for(var i=0; i<series.length; i++) {
if(series[i].visible) {
nb_of_visible_series++:
}
}
//If too many series are visible I'll randomly
//hide as many series as necessary
if(nb_of_visible_series>3) {
var nb_of_series_to_hide = nb_of_visible_series-3;
while(nb_of_series_to_hide>0) {
var i=Math.floor(Math.random()*series.length);
if(series[i].visible) {
series[i].hide()
nb_of_series_to_hide--;
}
}
}
}
}
}
So this is the idea but I don't know where to put it for real (not directly in the plotOptions.series field just like this I guess ?). I can put it in plotOptions.series.events.legentItemClick but then it will not be taken into account at the loading of the chart.
I'm looking for some tracks and advices about my code (I'm a JS beginner) and thank you in Advance. And sorry about my poor english.
For sure code you have written wouldn't work. Options for Highcharts should be javascript object, not some thing mixed between variables, options etc.
1) To get displayed on init only three series preprocess data, something like this:
var series = [{ data: [..], name: 'name 1' ..} , { data: [..], name: 'name 2' ..} , ... , {data: [..], name: 'name n'}];
for (var i = 0, len = series.length; i < len; i++) {
series[i].visible = i < 3; //setup variable series.visible to show/hide on init load.
}
$('#container').highcharts({
series: series //pass variable with updated visible option
});
2) As you noticed you need to write your own function for legendItemClick which will check how many series is visible (loop through chart.series and count series.visible == true). Then hide/show specific series using series.hide() / series.show().