Highcharts: Data not working correctly from JSON object - javascript

I am setting up a bubble chart with the following JSON object: (named donorArray in the code)
{1:{id:1, x:10, y:"88.88", z:"88.88", url:"http://ati.publishwhatyoufund.org/donor/usmcc/"}, 2:{id:2, x:10, y:"87.26", z:"87.26", url:"http://ati.publishwhatyoufund.org/donor/gavi/"}, 3:{id:3, x:10, y:"83.49", z:"83.49", url:"http://ati.publishwhatyoufund.org/donor/ukdfid/"}, 4:{id:4, x:10, y:"83.38", z:"83.38", url:"http://ati.publishwhatyoufund.org/donor/undp/"}, 5:{id:5, x:10, y:"73.81", z:"73.81", url:"http://ati.publishwhatyoufund.org/donor/world-bank-ida/"}, 6:{id:6, x:10, y:"70.65", z:"70.65", url:"http://ati.publishwhatyoufund.org/donor/global-fund/"}, 7:{id:7, x:10, y:"63.70", z:"63.70", url:"http://ati.publishwhatyoufund.org/donor/afdb/"}, 8:{id:8, x:10, y:"62.58", z:"62.58", url:"http://ati.publishwhatyoufund.org/donor/canada/"}, 9:{id:9, x:10, y:"60.38", z:"60.38", url:"http://ati.publishwhatyoufund.org/donor/sweden/"}, 10:{id:10, x:10, y:"57.64", z:"57.64", url:"http://ati.publishwhatyoufund.org/donor/asdb/"}, 11:{id:11, x:10, y:"57.11", z:"57.11", url:"http://ati.publishwhatyoufund.org/donor/iadb/"}, 12:{id:12, x:10, y:"54.24", z:"54.24", url:"http://ati.publishwhatyoufund.org/donor/ececho/"}, 13:{id:13, x:10, y:"52.11", z:"52.11", url:"http://ati.publishwhatyoufund.org/donor/ecdevco/"}, 14:{id:14, x:10, y:"51.14", z:"51.14", url:"http://ati.publishwhatyoufund.org/donor/ecfpi/"}, 15:{id:15, x:10, y:"50.70", z:"50.70", url:"http://ati.publishwhatyoufund.org/donor/denmark/"}, 16:{id:16, x:10, y:"49.37", z:"49.37", url:"http://ati.publishwhatyoufund.org/donor/netherlands/"}}
Here is my actual code:
jQuery(document).ready(function($){
scores = [];
for(i in donorArray){
score = parseFloat(donorArray[i].score);
score = Math.round(score * 100) / 100;
}
var $report= $('#report');
$report.html('Donor Scoring');
chart = new Highcharts.Chart({
chart: {
type: 'bubble',
renderTo: 'graph',
backgroundColor: 'transparent',
events: {
load: function() {
this.renderer.image('http://ati.publishwhatyoufund.org/wp-content/themes/ati/img/new_bg.png', 230, 20, 720, 720).add(); // add image(url, x, y, w, h)
}
}
},
plotOptions: {
bubble: {
color: 'white',
marker: {
fillColor: 'transparent'
}
},
point: {
allowPointSelect: false,
events: {
mouseOver: function(event) {
this.css("border", "1px solid black");
},
mouseOut: function(event) {
},
click: function(event) {
if(!this.selected) {window.open(this.options.url,'_self' );}
},
}
}
},
title: {
text: ''
},
credits: {
enabled: false
},
tooltip: {
enabled: false
},
yAxis: {
gridLineColor: 'transparent',
lineColor: 'transparent',
labels: {
enabled: false
}
},
xAxis: {
gridLineColor: 'transparent',
lineColor: 'transparent',
labels: {
enabled: false
},
offset: 0,
margin: 0
},
legend: {
enabled: false
},
series: {
data: donorArray
}
});
});
It renders the background and the graph container etc, but no datapoints(bubbles) appear.
Can you spot any obvious errors?
Thanks
Jacques

First of all, that part of code is properly wrong:
scores = [];
for(i in donorArray){
score = parseFloat(donorArray[i].score);
score = Math.round(score * 100) / 100;
}
I don't see any score in your donorArray objects, also, it will overwrite score, to become number/string, not adding to the array. Should be rather:
scores = [];
var temp;
for(i in donorArray){
temp = parseFloat(donorArray[i].score);
scores.push(Math.round(temp * 100) / 100);
}
Now, as #Abdul Jabbar said, your data format is just wrong. Doesn't suit Highcharts formats. Working example: http://jsfiddle.net/2ra0gnd0/2/ and code:
scores = [];
var temp;
var point;
var dataForChart = [];
for(i in donorArray){
point = donorArray[i];
temp = parseFloat(donorArray[i].score);
scores.push(Math.round(temp * 100) / 100);
dataForChart.push({
x: point.x,
id: point.id,
y: parseFloat(point.y),
z: parseFloat(point.z),
url: point.url
});
}
And last thing, to be fixed, is series:
series: {
data: donorArray
}
Should be of course an array of objects, not an object, so should be:
series: [{
data: dataForChart
}]

Related

Two synchronized vertical lines in highcharts

I recently came across this really nice example: https://jsfiddle.net/BlackLabel/7t59w4po/
Basically, what it does is that it synchronizes the drag of a line in one graph in all the other graphs.
I was wondering if someone could help me out to reproduce the same example, but instead of one vertical line, I would like to have two. Is this possible?
Thank you!
JS Code:
/*
The purpose of this demo is to demonstrate how multiple charts on the same page
can be linked through DOM and Highcharts events and API methods. It takes a
standard Highcharts config with a small variation for each data set, and a
mouse/touch event handler to bind the charts together.
*/
/**
* In order to synchronize tooltips and crosshairs, override the
* built-in events with handlers defined on the parent element.
*/
['mousemove', 'touchmove', 'touchstart'].forEach(function(eventType) {
document.getElementById('container').addEventListener(
eventType,
function(e) {
var chart,
point,
i,
event;
for (i = 0; i < Highcharts.charts.length; i = i + 1) {
chart = Highcharts.charts[i];
// Find coordinates within the chart
event = chart.pointer.normalize(e);
// Get the hovered point
point = chart.series[0].searchPoint(event, true);
if (point) {
point.highlight(e);
}
}
}
);
});
/**
* Override the reset function, we don't need to hide the tooltips and
* crosshairs.
*/
Highcharts.Pointer.prototype.reset = function() {
return undefined;
};
/**
* Highlight a point by showing tooltip, setting hover state and draw crosshair
*/
Highcharts.Point.prototype.highlight = function(event) {
event = this.series.chart.pointer.normalize(event);
this.onMouseOver(); // Show the hover marker
this.series.chart.tooltip.refresh(this); // Show the tooltip
this.series.chart.xAxis[0].drawCrosshair(event, this); // Show the crosshair
};
/**
* Synchronize zooming through the setExtremes event handler.
*/
function syncExtremes(e) {
var thisChart = this.chart;
if (e.trigger !== 'syncExtremes') { // Prevent feedback loop
Highcharts.each(Highcharts.charts, function(chart) {
if (chart !== thisChart) {
if (chart.xAxis[0].setExtremes) { // It is null while updating
chart.xAxis[0].setExtremes(
e.min,
e.max,
undefined,
false, {
trigger: 'syncExtremes'
}
);
}
}
});
}
}
/**
* Synchronize annotations drag&drop
*/
function syncAnnotations(e) {
var thisChart = this.chart;
var newX = this.options.shapes[0].points[0].x
if (e.type !== 'afterUpdate') {
Highcharts.each(Highcharts.charts, function(chart) {
if (chart !== thisChart) {
chart.annotations[0].update({
labels: [{
point: {
x: newX
}
}],
shapes: [{
points: [{
x: newX,
xAxis: 0,
y: 0
}, {
x: newX,
xAxis: 0,
y: 1000
}]
}]
});
}
});
}
}
// Get the data. The contents of the data file can be viewed at
Highcharts.ajax({
url: 'https://cdn.jsdelivr.net/gh/highcharts/highcharts#v7.0.0/samples/data/activity.json',
dataType: 'text',
success: function(activity) {
activity = JSON.parse(activity);
activity.datasets.forEach(function(dataset, i) {
// Add X values
dataset.data = Highcharts.map(dataset.data, function(val, j) {
return [activity.xData[j], val];
});
var chartDiv = document.createElement('div');
chartDiv.className = 'chart';
document.getElementById('container').appendChild(chartDiv);
Highcharts.chart(chartDiv, {
chart: {
marginLeft: 40, // Keep all charts left aligned
spacingTop: 20,
spacingBottom: 20
},
title: {
text: dataset.name,
align: 'left',
margin: 0,
x: 30
},
credits: {
enabled: false
},
legend: {
enabled: false
},
xAxis: {
crosshair: true,
events: {
setExtremes: syncExtremes
},
labels: {
format: '{value} km'
}
},
yAxis: {
title: {
text: null
}
},
annotations: [{
draggable: 'x',
animation: {
defer: false
},
events: {
drag: syncAnnotations,
afterUpdate: syncAnnotations
},
shapes: [{
strokeWidth: 3,
type: 'path',
points: [{
x: 3,
y: 0,
xAxis: 0
}, {
x: 3,
y: 1000,
xAxis: 0
}]
}],
labels: [{
point: {
x: 3,
y: 30,
xAxis: 0
},
shape: 'rect',
formatter: function(e) {
// Use shape options because value is available there. Label use translation only
return this.target.annotation.shapes[0].options.points[0].x.toFixed(3);
}
}]
}],
tooltip: {
positioner: function() {
return {
// right aligned
x: this.chart.chartWidth - this.label.width,
y: 10 // align to title
};
},
borderWidth: 0,
backgroundColor: 'none',
pointFormat: '{point.y}',
headerFormat: '',
shadow: false,
style: {
fontSize: '18px'
},
valueDecimals: dataset.valueDecimals
},
series: [{
data: dataset.data,
name: dataset.name,
type: dataset.type,
color: Highcharts.getOptions().colors[i],
fillOpacity: 0.3,
tooltip: {
valueSuffix: ' ' + dataset.unit
}
}]
});
});
}
});
You only need to add another annotation:
annotations: [{
...,
{
...
}],
And improve the syncAnnotations function a little bit:
function syncAnnotations(e) {
var thisChart = this.chart;
var newX = this.options.shapes[0].points[0].x
var index = this.chart.annotations.indexOf(this);
if (e.type !== 'afterUpdate') {
Highcharts.each(Highcharts.charts, function(chart) {
if (chart !== thisChart) {
chart.annotations[index].update({
...
});
}
});
}
}
Live demo: https://jsfiddle.net/BlackLabel/jwtLc379/
API Reference: https://api.highcharts.com/highcharts/annotations

Highcharts: Value will not be updated

i have the next problem with Highcharts. This is a new Highchart for an other site.
See here: https://imgur.com/a/VQQLU
The arrow show to -3 Megawatts but the value at the bottom shows another value. At the first pageload the values are identical, but there comes all 5 seconds new values. And they are not updated at the bottom.
Edit: The tolltip will be updated correctly.
My code:
$(function () {
$.getJSON('jsonlive.php', function(chartData) {
var ADatum; var Eheit; var AktL; var MinL; var MaxL; var chartValue; var i;
ADatum = chartData[0].AktDatum;
Eheit = chartData[0].Einheit;
AktL = chartData[0].AktuelleLeistung;
MinL = chartData[0].MinLeistung;
MaxL = chartData[0].MaxLeistung;
var tMin = (MinL*-1); var tMax = MaxL;
var ttt = new Array();
if (tMin < tMax) { chartValue = tMax; } else if (tMin > tMax) { chartValue = tMin; } // Ermitteln ob neg/pos Zahl die größere ist.
ttt[0] = (chartValue*-1); // Skala mit Zahlen beschriften
for (i = 1; i < chartValue; i++) { ttt[i] = (i*-1); }
var tz = ttt.length ;
for (i = 0; i < chartValue; i++) { ttt[(tz+i)] = i; }
ttt[ttt.length] = chartValue;
var gaugeOptions = {
chart:{ events: {
load: function () { setInterval(function () {
$.getJSON('jsonlive.php', function(chartData) {
ADatum = chartData[0].AktDatum;
AktL = chartData[0].AktuelleLeistung;
var point = $('#inhalt').highcharts().series[0].setData([AktL], true);
});}, 5000);}
}, type: 'gauge' },
title: null,
pane: {
center: ['50%', '85%'], size: '140%', startAngle: -90, endAngle: 90,
background: [{
backgroundColor: {
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
stops: [[0, '#00fb00'],[1, '#003f00']]},
borderWidth: 2,
outerRadius: '109%',
innerRadius: '102%', shape: 'arc' }]
},
series: [{
data: [AktL],
dataLabels: { borderWidth: 0,align: 'center',x: 0,y: 110,
format: '<div style="text-align:center;font-size:24px;color:black">'+AktL+' ' +Eheit+'</span></div>'
}
}],
tooltip: {
formatter: function () { return 'Datum: <b>' + (new Date(ADatum).toLocaleString("de-DE", { timeZone: 'UTC' })) +
'</b> <br>Leistung <b>' + AktL + ' ' + Eheit + '</b>';}, enabled: true },
yAxis: {lineWidth: 10, minorTickInterval: null, tickPixelInterval: 100, tickWidth: 5, title: { y: -250 }, labels: { y: 2 }}
};
// Anzeige
$('#inhalt').highcharts(Highcharts.merge(gaugeOptions, {
yAxis: {
min: (chartValue*-1),max: chartValue,tickPositions: ttt,tickColor: '#666',minorTickColor: '#666',
plotBands: [{ // optionaler Bereich, zeigt von 0-1 grün, 1 bis hälfte maximum gelb, und hälfte max bis max rot
from: 0, to: -1, color: '#55BF3B' }, { // green
from: -1, to: ((chartValue*-1)/2), color: '#DDDF0D' }, { // yellow
from: ((chartValue*-1)/2),to: (chartValue*-1),color: '#DF5353' }, { // red
from: 0,to: 1,color: '#55BF3B' }, { // green
from: 1,to: (chartValue/2),color: '#DDDF0D' }, { // yellow
from: (chartValue/2),to: chartValue,color: '#DF5353' }],// red
title: { style: { color: 'black', fontWeight: 'bold', fontSize: '24px' }, text: 'Leistung in '+Eheit },
labels: { formatter: function () { return this.value; }}},
credits: { enabled: false } // Link auf highcharts rechts unten an/aus
}));
});
});
</script>
The problem here is that you use a hard-coded value (AktL) in your dataLabels.format. In your example format is just a string that's used all the time.
Use {point.y} to have the label updated on every setData():
series: [{
data: [val],
dataLabels: {
// format: val // WONT WORK
format: '{point.y}'
}
}],
Live demo: http://jsfiddle.net/BlackLabel/v28q5n09/

How to contain category data in tooltip

I've seen tutorials and posts about getting data from the x axis into the tooltip but I am overriding it with categories and cannot figure out how to get the x axis to show up in the tooltip.
This is what im working with:
function showTooltip(x, y, contents) {
$('<div id="tooltip" class="flot-tooltip tooltip"><div class="tooltip-arrow"></div>' + contents + '</div>').css({
top: y - 43,
left: x - 15,
}).appendTo("body").fadeIn(200);
}
var data = [[1492854610, -1240],[1492939020, -1273],[1493025073, -1279],[1493117066, -1186],[1493198484, -1269],[1493289175, -1198],[1493370646, -1280],[1493458518, -1255],[1493543731, -1275],[1493630250, -1273],[1493716306, -1279],[1493803609, -1264],[1493889258, -1276],[1493975557, -1278],[1494064529, -1235],[1494155440, -1160],[1494237980, -1224],[1494321047, -1280],[1494407990, -1271],[1494494125, -1275],[1494581609, -1257],[1494668321, -1252],[1494753220, -1277],[1494847855, -1140],[1494925963, -1278],[1495012537, -1275],[1495099289, -1269],[1495188205, -1227],[1495273568, -1244],[1495358329, -1272]];
$.plot($("#placeholder"), [{
label: "Delay: ",
data: data,
color: "#3a8ce5"
}], {
xaxis: {
mode: "categories",
tickLength: 0,
ticks: [[0, "1:50 AM"],[1, "1:17 AM"],[2, "1:11 AM"],[3, "2:44 AM"],[4, "1:21 AM"],[5, "2:32 AM"],[6, "1:10 AM"],[7, "1:35 AM"],[8, "1:15 AM"],[9, "1:17 AM"],[10, "1:11 AM"],[11, "1:26 AM"],[12, "1:14 AM"],[13, "1:12 AM"],[14, "1:55 AM"],[15, "3:10 AM"],[16, "2:06 AM"],[17, "1:10 AM"],[18, "1:19 AM"],[19, "1:15 AM"],[20, "1:33 AM"],[21, "1:38 AM"],[22, "1:13 AM"],[23, "3:30 AM"],[24, "1:12 AM"],[25, "1:15 AM"],[26, "1:21 AM"],[27, "2:03 AM"],[28, "1:46 AM"],[29, "1:18 AM"]]
},
yaxis: {
min: -2000,
max: 1000,
},
series: {
lines: {
show: true,
fill: true
},
points: {
show: true,
}
},
grid: {
hoverable: true,
clickable: true,
markings: [
{ color: '#000', lineWidth: 1, yaxis: { from: 0, to: 0 } },
]
},
legend: {
show: false
}
});
$("#placeholder").bind("plothover", function(event, pos, item) {
if (item) {
if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex;
$("#tooltip").remove();
var y = item.datapoint[1].toFixed();
showTooltip(item.pageX, item.pageY,
item.series.label + " = " + y);
}
} else {
$("#tooltip").remove();
previousPoint = null;
}
});
I am trying to get the times part of the categories. The item array has 3 pieces of data, none of which are the times
jFiddle:
http://jsfiddle.net/zw14y8c3/2/
The item.datapoint[0] data has the index of the x-axis tick. With that you can get the actual tick label from the ticks array:
var x = $("#placeholder").data('plot').getAxes().xaxis.ticks[item.datapoint[0]].label;
See the updated fiddle for the full example.

How to divide data from the series in highcharts

I want to process data from a .csv file to:
Divide the data coming in by 10, e.g., 588 => 58.8
Remove outliers from the data or to change to zero, e.g., 8888 => 0
Here is my javascript, I appreciate the help!!
$.get('http://www.geoinc.org/Dropbox/geo/sites/GC_ROOM/charts/hassayampa.csv', function(data)
{
// Split the lines
var lines = data.split('\n');
var i = 0;
var csvData = [];
// Iterate over the lines and add categories or series
$.each(lines, function(lineNo, line)
{
csvData[i] = line.split(',');
i = i + 1;
});
var columns = csvData[0];
var categories = [], series = [];
for(var colIndex=0,len=columns.length; colIndex<len; colIndex++)
{
//first row data as series's name
var seriesItem=
{
data:[],
name:csvData[0][colIndex]
};
for(var rowIndex=1,rowCnt=csvData.length; rowIndex<rowCnt; rowIndex++)
{
//first column data as categories,
if (colIndex == 0)
{
categories.push(csvData[rowIndex][0]);
}
else if(parseFloat(csvData[rowIndex][colIndex])) // <-- here
{
seriesItem.data.push(parseFloat(csvData[rowIndex][colIndex]));
}
};
//except first column
if(colIndex>0)series.push(seriesItem);
}
// Create the chart
var chart = new Highcharts.Chart(
{
chart:
{
renderTo: 'test',
type: 'line',
zoomType: 'x',
},
title: {
text: 'Daily Average Temperature',
x: -20 //center
},
subtitle: {
text: 'Source: HASSAYAMPA',
x: -20
},
xAxis:
{
categories: categories,
labels:
{
step: 80,
},
tickWidth: 0
},
yAxis:
{
title: {
text: 'Temperature (\xB0C)'
},
//min: 0
},
tooltip:
{
formatter: function()
{
return '<b>'+ this.series.name +'</b><br/>'+ this.x +': '+ this.y +'\xB0C';
}
},
legend:
{
layout: 'vertical',
//backgroundColor: '#FFFFFF',
//floating: true,
align: 'left',
//x: 100,
verticalAlign: 'top',
//y: 70,
borderWidth: 0
},
plotOptions:
{
area:
{
animation: false,
stacking: 'normal',
lineColor: '#666666',
lineWidth: 1,
marker:
{
lineWidth: 1,
lineColor: '#666666'
}
}
},
series: series
});
});
I'm not sure what you are asking, but I'll take a shot at it...
First things first, this snippet of code is not sound. It'll not only skip NaNs but 0s as well (which is valid numeric data):
else if(parseFloat(csvData[rowIndex][colIndex]))
{
seriesItem.data.push(parseFloat(csvData[rowIndex][colIndex]));
}
Instead I'd do:
//first column data as categories,
if (colIndex == 0)
{
categories.push(csvData[rowIndex][0]);
}
else
{
var fVal = parseFloat(csvData[rowIndex][colIndex]);
if (!isNaN(fVal))
{
fVal = fVal / 10.0; //<-- here's the division!!
seriesItem.data.push(fVal);
}
}
As far as how to exclude outliers, the big question there is how do you want to exclude outliers? A simple min/max criteria? Then just check that fVal is within those limits before seriesItem.data.push...

Donut Slices Not Visible On Load

Here is a jsFiddle for an issue i have been trying to solve:
http://jsfiddle.net/kSSYg/
When the donut chart loads, the slices are not visible, but the legends are. When you hover over, they appear.
Has anyone else encountered this?
code
$(function () {
var chart;
$(document).ready(function() {
var colors = Highcharts.getOptions().colors,
categories = ['Security', 'Interfaces', 'SNMP', 'Management', 'General'],
name = 'Rule Categories',
data = [{"y":23.53,"drilldown":{"name":"Security","categories":["Pass","Fail"],"data":[11.77,11.77]}},{"y":23.53,"drilldown":{"name":"Interfaces","categories":["Pass","Fail"],"data":[23.53,0]}},{"y":23.53,"drilldown":{"name":"SNMP","categories":["Pass","Fail"],"data":[11.77,11.77]}},{"y":5.88,"drilldown":{"name":"Management","categories":["Pass","Fail"],"data":[5.88,0]}},{"y":23.53,"drilldown":{"name":"General","categories":["Pass","Fail"],"data":[23.53,0]}}];
// Build the data arrays
var browserData = [];
var versionsData = [];
for (var i = 0; i < data.length; i++) {
// add browser data
browserData.push({
name: categories[i],
y: data[i].y,
color: data[i].color
});
// add version data
for (var j = 0; j < data[i].drilldown.data.length; j++) {
var brightness = 0.2 - (j / data[i].drilldown.data.length) / 5 ;
versionsData.push({
name: data[i].drilldown.categories[j],
y: data[i].drilldown.data[j],
color: Highcharts.Color(data[i].color).brighten(brightness).get()
});
}
}
// Create the chart
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'pie'
},
title: {
text: 'Browser market share, April, 2011'
},
yAxis: {
title: {
text: 'Total percent market share'
}
},
plotOptions: {
pie: {
shadow: false
}
},
tooltip: {
valueSuffix: '%'
},
series: [{
name: 'Browsers',
data: browserData,
size: '60%',
dataLabels: {
formatter: function() {
return this.y > 5 ? this.point.name : null;
},
color: 'white',
distance: -30
}
}, {
name: 'Versions',
data: versionsData,
innerSize: '60%',
dataLabels: {
formatter: function() {
// display only if larger than 1
return this.y > 1 ? '<b>'+ this.point.name +':</b> '+ this.y +'%' : null;
}
}
}]
});
});
});​
Do you have to define your own colors? If you remove the two lines which are setting the colors, it works. See http://jsfiddle.net/kSSYg/2/
remove:
color: data[i].color
and
color: Highcharts.Color(data[i].color).brighten(brightness).get()
The reason these lines are not working is because your data array objects do not define the attribute "color"

Categories