I am trying to dynamically load in a number of series, depending on projects chosen by the user. I am using Laravel 5.2, PHP 5.6 and HighCharts.
I have managed to load in one JSON file, which is generated when the user selects projects. But I would like it if the JavaScript could parse the different series from the JSON file and dynamically load this into the series.
This is the code which I am using:
$(function () {
// Set up the chart
var processed_json = new Array();
$.getJSON('/uploads/test.json', function(data) {
for (i = 0; i < data.length; i++) {
processed_json.push([data[i].key, data[i].value]);
}
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'column',
options3d: {
enabled: true,
alpha: 0,
beta: 0,
depth: 0,
viewDistance: 25
}
},
title: {
text: 'Grades'
},
subtitle: {
text: 'Dataset'
},
plotOptions: {
column: {
depth: 0
}
},
series: [{
name: 'Grades',
data: processed_json
}],
credits: {
enabled: false
}
});
function showValues() {
$('#alpha-value').html(chart.options.chart.options3d.alpha);
$('#beta-value').html(chart.options.chart.options3d.beta);
$('#depth-value').html(chart.options.chart.options3d.depth);
}
// Activate the sliders
$('#sliders input').on('input change', function () {
chart.options.chart.options3d[this.id] = this.value;
showValues();
chart.redraw(false);
});
showValues();
});
});
My JSON is formatted like:
[{"key":"Math","value":6},{"key":"Biology","value":"8"},{"key":"English","value":"7"},{"key":"Gym","value":"4"}]
So I would like to have more JSONs like so, in one file to be parsed in the Javascript and be loaded in into the series.
Thank you!
EDIT
thanks for your reply. I have edited my code:
$(function () {
var processed_json = new Array();
var options = {
chart: {
renderTo: 'container',
type: 'column',
options3d: {
enabled: true,
alpha: 0,
beta: 0,
depth: 0,
viewDistance: 25
}
},
title: {
text: 'Grades'
},
subtitle: {
text: 'Dataset'
},
plotOptions: {
column: {
depth: 0
}
},
series: [{
}],
credits: {
enabled: false
}
};
$.getJSON('/uploads/test.json', function(data) {
for (i = 0; i < data.length; i++) {
processed_json.push([data[i].key, data[i].value]);
}
});
options.series[0].remove();
options.series[0].setData = {
name: 'Grades',
data: processed_json
}
var chart = new Highcharts.Chart(options);
chart.redraw(true);
function showValues() {
$('#alpha-value').html(chart.options.chart.options3d.alpha);
$('#beta-value').html(chart.options.chart.options3d.beta);
$('#depth-value').html(chart.options.chart.options3d.depth);
}
// Activate the sliders
$('#sliders input').on('input change', function () {
chart.options.chart.options3d[this.id] = this.value;
showValues();
chart.redraw(false);
});
showValues();
});
But nothing is displayed anymore and the following error is given
TypeError: options.series[0].remove is not a function
I have also tried
var chart = new Highcharts.Chart(options);
chart.series[0].remove();
chart.series[0].setData = {
name: 'Grades',
data: processed_json
}
chart.redraw(true);
But this gives:
TypeError: Cannot set property 'setData' of undefined
I think highcharts has a method chart.addSeries for adding a new series. If you want to replace the current series with a new series, you can try removing first the current series using chart.series[0].remove( ) then add the new series with chart.addSeries. The parameter for the chart.addSeries can be an object like your
{
name: 'Grades',
data: processed_json
}
Then, define method with load data.. example:
function(chart) {
$.each(chart.series, function(i, v){
chart.series[i].remove(true);
});
chart.addSeries({your_data}, true);
}
check http://api.highcharts.com/highcharts/Chart.addSeries/Chart.addSeries
In my webapp, i use 10 of 15 types of graphs highchart and all dynamically load and work fine :) Highcharts is awesome.
Aim: I have two identical Highcharts treemaps and if I select one point of one chart, I also want to send a select event to the second chart's point with the same id/ same position.
Progress:
I followed these answers that tackle the same problem, only for line graphs, and then adopted the fiddle posted there for treemaps. You can find it here as well as below:
$(function () {
var prevPid = 0;
var chart = {
plotOptions: {
series: {
allowPointSelect: true,
point: {
'events': {
select: function () {
var pId = this.series.data.indexOf(this);
var chart1 = $('#container').highcharts();
var chart2 = $('#container2').highcharts();
chart1.series[0].data[pId].setState('select');
chart2.series[0].data[pId].setState('select');
chart2.series[0].data[prevPid].setState('');
prevPid = pId;
}
}
}
}
},
series: [{
type: "treemap",
data: [{
name: 'A',
value: 6,
colorValue: 1
}, {
name: 'B',
value: 6,
colorValue: 2
}, {
name: 'C',
value: 4,
colorValue: 3
}]
}]
};
$('#container').highcharts(chart);
$('#container2').highcharts(chart);
});
Problem: However the corresponding point of the other chart is not selected. Any advice on how to fix it?
Highcharts v5+
Instead of playing around with states, it's easier to use point.update(), demo: http://jsfiddle.net/BlackLabel/hy12z5u7/
Settings:
chart: {
events: {
load: function() {
$.each(this.series, function(i, s) {
$.each(s.data, function(j, p) {
p.pointAttr = {
select: {
color: "red"
}
};
});
});
}
}
},
And action:
point: {
'events': {
click: function() {
var pId = this.series.data.indexOf(this);
var chart1 = $('#container').highcharts();
var chart2 = $('#container2').highcharts();
chart1.series[0].data[prevPid].update({
color: chart1.series[0].color
});
chart2.series[0].data[prevPid].update({
color: chart2.series[0].color
});
chart1.series[0].data[pId].update({
color: chart1.series[0].data[pId].pointAttr.select.color
});
chart2.series[0].data[pId].update({
color: chart2.series[0].data[pId].pointAttr.select.color
});
prevPid = pId;
}
}
}
Highcharts < v4
The problem is that treemap doesn't have states.select option (API: http://api.highcharts.com/highcharts#plotOptions.treemap.states ) so even, when you force select-ed state, then nothing visually changes on your chart. You can add that state manually: http://jsfiddle.net/tqa6uxdb/3/
chart: {
events: {
load: function() {
$.each(this.series, function(i, s) {
$.each(s.data, function(j, p) {
p.pointAttr.select = {
fill: "red"
}
});
});
}
}
},
Note: your logic for selecting/deselecting points is missing checking if currently clicked point is already clicked.
I am working with Highcharts and live data. I have my ajax all set up properly it seems and have a setTimeout called to bring in live data. Whenever that data comes in I want to addPoint() to my series and draw the new graph (shifting to the left). Below is my code, line 85 is the .addPoint call but you will see in the console that it is showing as not a function or undefined.
I know from the console as well that I am a calling my data correctly from my chart (chart1.data.series[0] returns and object). Here is the highcharts documentation on series data and addPoint : < http://api.highcharts.com/highcharts#Series.addPoint >
Any idea where I went wrong? I am new to js 1 year <. so I appreciate all your help!
<!doctype html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
</head>
<body>
<div id="container" style="width:100%"></div>
</body>
<script>
chart1 = {
yAxisMin: null,
yAxisMax: null
};
// empty objects for our data and to create chart
seriesData = [];
BPM = [];
time1 = [];
// console.log(chart1.data.series);
$(function() {
$(document).ready(function() {
Highcharts.setOptions({
global: {
useUTC: false
}
});
function requestData() {
var url = 'http://msbandhealth.azurewebsites.net/odata/PulsesAPI/';
$.ajax({
url: url,
dataType: 'json',
context: seriesData,
success: function(data) {
shift = chart1.data.series[0].data.length > 20;
// structure our data
for (var i = 0; i < data.value.length; i++) {
bpm = data.value[i].BPM;
time = data.value[i].Time;
console.log(time);
this.push([time, BPM]);
BPM.push(bpm);
time1.push(time);
}
// console.log(series[0]);
// find the highest pulse so we can set it to the highest y point
chart1.yAxisMax = (function(array) {
var pulse_array = [];
for (var i = 0; i < array.length; i++) {
if (array[i] != null) {
pulse_array.push(array[i]);
}
}
return Math.max.apply(Math, pulse_array);
})(BPM);
// find the lowest pulse rate and set it to lowest y point
chart1.yAxisMin = (function(array) {
var pulse_array = [];
for (var i = 0; i < array.length; i++) {
if (array[i] != null) {
pulse_array.push(array[i]);
}
}
return Math.min.apply(Math, pulse_array);
})(BPM);
// set our data series and create new chart
chart1.data.series[0].data = BPM;
chart = new Highcharts.Chart(chart1.data);
$('#container').css({
height: '400px'
});
chart1.data.series[0].addPoint(BPM, true, true);
// setTimeout(requestData, 3000);
console.log(chart1.data.series);
}
});
}
// give highcharts something to render to
container = document.getElementById("container");
chart1.data = {
chart: {
renderTo: container,
type: 'spline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: requestData()
}
},
title: {
text: ' Real Time Pulse Analysis'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
min: chart1.yAxisMin,
max: chart1.yAxisMax,
title: {
text: 'Heart Rate'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
formatter: function() {
return '<b>' + this.series.name + '</b><br/>' +
Highcharts.dateFormat('%H:%M:%S', this.x) + '<br/>' +
Highcharts.numberFormat(this.y, 2);
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Beats Per Minute',
data: []
}]
};
});
});
</script>
</html>
You should use reference to chart and then call addPoint, instead of refer to chart configuration object.
Correct form: chart.series[0].addPoint()
I'm using Highcharts.visualize to draw the graph from a table containing the data.
You can test my working code here: http://jsfiddle.net/S2XM8/1/
I have two questions:
I want to have a separate styling for my "Additional value". How do I go about it?
Can I add data for the X-axis via the javascript? For example if I need to fill in the gap between 2014-05-27 and 2014-05-25 in the table.
Highcharts.visualize = function (table, options, tableClass) {
// the categories
options.xAxis.categories = [];
$('tbody th', table).each( function () {
options.xAxis.categories.push(this.innerHTML);
});
// the data series
options.series = [];
$('tr', table).each( function (i) {
var tr = this;
$('.graph', tr).each( function (j) {
if (i === 0) { // get the name and init the series
options.series[j] = {
name: this.innerHTML,
data: []
};
} else { // add values
options.series[j].data.push(parseFloat(this.innerHTML));
console.log(this.innerHTML);
}
});
});
options.title = { text: 'Some graph' };
$('#' + tableClass + '-graph').highcharts(options);
};
var tableNumber = document.getElementById('rank-table'),
options = {
chart: {
zoomType: 'x'
},
xAxis: {
tickInterval: 30,
reversed: true,
labels: {
rotation: 45
},
type: 'datetime',
dateTimeLabelFormats: { // don't display the dummy year
month: '%e. %b',
year: '%b'
}
},
yAxis: {
title: {
text: 'Rank'
},
min: 1,
reversed: true
},
legend: {
layout: 'vertical',
align: 'middle',
verticalAlign: 'bottom',
borderWidth: 0
}
};
Highcharts.visualize(tableNumber, options, 'number');
Both things are possible, but require to modify visualize method, see: http://jsfiddle.net/S2XM8/4/
You can set series options in a chart and then merge with data:
series: [{
// nothing special
}, {
type: 'column' // set series type for example
}]
And merging:
options.series[j] = options.series[j] || {};
options.series[j].name = this.innerHTML,
options.series[j].data = [];
Check parsed value before passing as point value:
var value = parseFloat(this.innerHTML);
if(isNaN(value)) { //null value - produces NaN when parsing
options.series[j].data.push(10);
} else {
options.series[j].data.push(value); // push value to the series
}
Trying to get some help with this weird behavior.
I managed to get the highcharts chart, multiple series etc. all setup. When using static values from a inline array, the values are assigned correctly to the chart, but if I pull the numbers out of a csv file, they are not assigned unless I pause execution with an alert message. Please see code below
$(function () {
// every row on report needs
// category defined (left side)
var mycategories = [];
// every column on report needs
// seriesname defined
var headers = [];
var myseriesnames = [];
var lines = [];
var line_tokens = [];
// Read data from csv file
$.get('top10raj.csv', function(data) {
// Split the lines
lines = data.split('\n');
console.log("First line : "+ lines[0]);
headers = lines[0].split(',');
for (var i = 1; i < headers.length; i++) {
myseriesnames.push(headers[i]);
}
//
// display all lines
//
for (var i = 1; i < lines.length; i++) {
line_tokens = lines[i].split(',');
console.log('Equip.No:' + line_tokens[0].trim()); // Equipment Number
console.log(line_tokens[1].trim()); // ActualCost
console.log(line_tokens[2].trim()); // ActualMaterial
console.log(line_tokens[3].trim()); // ActualLabor
console.log(line_tokens[4].trim()); // ActualOther
mycategories.push(line_tokens[0].trim());
}
});
alert('report ready');
var myarray = [7,6,7,8,7,8,3,4,1,4,7,8,7,5];
var serObj = [{ 'name': myseriesnames[0],
data:[8,9,8,6,5,2,3,6,5,7,4,5,8,9]
},
{ 'name': myseriesnames[1],
data:[8,5,6,9,8,7,4,5,2,5,8,7,8,6]
},
{ 'name': myseriesnames[2],
data: myarray
},
{ 'name': myseriesnames[3],
data: myarray
},
];
var chart = new Highcharts.Chart({
chart: {
renderTo:'container',
type: 'column'
},
title:{
text:'Chart Title'
},
tooltip:{
formatter:function(){
return '<b>' + this.series.name + '</b>' +
'<br/><b>Item Number:</b> ' + this.x + // X Value
'<br/><b>Amount:</b> ' + this.y + // Y Value
'<br/><b>Other Data:</b> ';// + this.point.note;
}
},
credits:{enabled:false},
legend:{
},
plotOptions: {
series: {
shadow:false,
borderWidth:0
}
},
xAxis:{
// Need to define categories for every row
// on the report (left side)
categories: mycategories,
lineColor:'#999',
lineWidth:1,
tickColor:'#666',
tickLength:3,
labels: { rotation:45, align:'left'},
title:{
text:'Equipment',
}
},
yAxis:{
lineColor:'#999',
lineWidth:1,
tickColor:'#666',
tickWidth:1,
tickLength:3,
gridLineColor:'#ddd',
title:{
text:'Amount (USD)',
rotation:-90,
margin:50,
}
},
series: serObj
});
});
EqptNumber,ActualTotal,ActualMaterial,ActualLabor,ActualOther,
111.3207B,666693.61,606564.37,53866.49,6262.75,
106.3355,588647.91,240175.91,322779.00,25693.00,
106.3307,364234.86,266598.36,97636.50,0,
125.L8702A,356025.49,347519.49,8506.00,0,
122.E8801A,340712.89,25483.39,33729.50,281500.00,
127.E2201,319372.29,112362.97,307731.88,100722.56,
107.3251A,310587.25,316225.36,35496.50,41134.61,
622.CW88105,307762.86,7957.36,299805.50,0,
133.1203A,307285.20,40273.19,249658.01,17354.00,
106.3352,278737.48,132009.49,146728.00,0.01,
107.3251ACC,310587.25,316225.36,35496.50,41134.61,
622.CW88105CC,307762.86,7957.36,299805.50,0,
133.1203ACC,307285.20,40273.19,249658.01,17354.00,
106.3352CC,278737.48,132009.49,146728.00,0.01,
The csv file I am using is shown at the bottom of the source.
if the following line
alert('report ready');
is commented out, I lose all the categories labels and they are replaced by 0..1,2,3.. etc. along the X-Axis. Trying hard to understand why this is happening, but so far no luck in fixing. Appreciate any help I can get with this, as I really want to use the Highcharts library with dynamic data and using only static data from predefined arrays is very limiting.
The problem is that your request for the csv file ($.get ) is executed asynchronously, meaning that the rest of your code is running before the data is returned. Try moving your code into the callback function, something like
//..your code
mycategories.push(line_tokens[0].trim());
}
//moved your code here
var myarray = [7,6,7,8,7,8,3,4,1,4,7,8,7,5];
var serObj = [{ 'name': myseriesnames[0],
data:[8,9,8,6,5,2,3,6,5,7,4,5,8,9]
},
{ 'name': myseriesnames[1],
data:[8,5,6,9,8,7,4,5,2,5,8,7,8,6]
},
{ 'name': myseriesnames[2],
data: myarray
},
{ 'name': myseriesnames[3],
data: myarray
},
];
var chart = new Highcharts.Chart({
chart: {
renderTo:'container',
type: 'column'
},
title:{
text:'Chart Title'
},
tooltip:{
formatter:function(){
return '<b>' + this.series.name + '</b>' +
'<br/><b>Item Number:</b> ' + this.x + // X Value
'<br/><b>Amount:</b> ' + this.y + // Y Value
'<br/><b>Other Data:</b> ';// + this.point.note;
}
},
credits:{enabled:false},
legend:{
},
plotOptions: {
series: {
shadow:false,
borderWidth:0
}
},
xAxis:{
// Need to define categories for every row
// on the report (left side)
categories: mycategories,
lineColor:'#999',
lineWidth:1,
tickColor:'#666',
tickLength:3,
labels: { rotation:45, align:'left'},
title:{
text:'Equipment',
}
},
yAxis:{
lineColor:'#999',
lineWidth:1,
tickColor:'#666',
tickWidth:1,
tickLength:3,
gridLineColor:'#ddd',
title:{
text:'Amount (USD)',
rotation:-90,
margin:50,
}
},
series: serObj
});
});
//here's where the alert used to be
///alert('report ready');
});