Highcharts -- Array not assigned without alert message - javascript

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');
});

Related

reading data from CSV and show continuous graph

I am trying to plot a chart which will read a data from csv file which is appending on every minute with latest data as per below format.
The chart will continue reading data from csv file and show the graph on every second wise. Can you please help me on this? I want to show the exact time which are coming from file should be show on graph.
CSV format..
time,count
18:01:00,3
18:01:01,4
....
$(document).ready(function () {
var csv = [],
x;
Highcharts.setOptions({
global: {
useUTC: false
}
});
var data = 'time,count\n18:01:00,3\n18:01:01,4';
//$.get('data.csv', function(data) {
var lines = data.split('\n');
$.each(lines, function(lineNo, line) {
if(lineNo > 0) {
var items = line.split(',');
useUTC: false;
x = items[0].split(':');
csv.push([Date.UTC(2015,1,1,x[0],x[1],x[2]), parseFloat(items[1])]);
}
});
console.log(csv);
$('#container').highcharts({
chart: {
renderTo: 'container',
type: 'spline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
useUTC: false,
events: {
load: function () {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function () {
var l = series.data.length - 1,
lastX = series.data[l].x;
$.get('data.csv', function(data) {
var lines = data.split('\n'),
len = lines.length,
items = lines[len - 1].split(','),
x = items[0].split(':'),
y = parseFloat(items[1]);
useUTC: false;
x = Date.UTC(2015,1,1,x[0],x[1],x[2]);
if(x !== lastX) {
series.addPoint([x, y], true, true);
}
});
}, 1000); //refresh each 1 second
}
}
},
title: {
text: 'TPS Data'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'Value'
},
plotLines: [{
value: 3,
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: 'Count',
data: csv
}]
});
//});
});
div {
min-width: 50px;
height: 200px;
margin: 0 auto;
}
<script type="text/javascript" src="http://code.jquery.com/jquery-1.12.0.js"></script>
<script type="text/javascript" src="http://code.highcharts.com/highcharts.js"></script>
<div id="container" style=""></div>
Note In the snippet I was replace the ajax function $.get with hardcoded data so it will show the result but the question is about the ajax way.

Highcharts visualize, style series

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
}

Update Highchart data form exported button

I'm trying to use the exporting option to add a button which is then used to switch between a line chart with the real point and another with the cumulative sum of them.
I'm using the following code:
$(function () {
$('#container').highcharts({
chart: {
type: 'line'
},
xAxis: {
tickPixelInterval: 200,
categories: jsonResponse["Date"]
},
series: {
data: jsonResponse["values"]
},
exporting: {
buttons: {
'myButton': {
_id: 'myButton',
symbol: 'diamond',
text: 'Cumulative',
x: -62,
symbolFill: '#B5C9DF',
hoverSymbolFill: '#779ABF',
onclick: function() {
if(!cumulative){
this.series[0].setData = cumcum(jsonResponse["values"]);
alert(this.series[1].setData);
cumulative = true;
} else {
this.series[0].setData = jsonResponse["values"];
cumulative = false;
alert(this.series[1].setData);
}
},
_titleKey: "myButtonTitle"
}
}
}
});
});
function cumcum(data){
var res = new Array();
res[0] = data[0];
for(var i=1; i<data.length; i++) {
res[i] = res[i-1] + data[i];
}
return res;
}
From the alert I can see that the data are correctly calculated but the plot stays the same.
I also tried series[0].yData and series[0].processedYData
setData is a function, you have to call it like:
this.series[0].setData(cumcum(jsonResponse["values"])
See API http://api.highcharts.com/highstock#Series for more information.

Unable to plot data json data on highcharts

I am trying to load json data to high-charts. I am receiving json data from DB using $.getJSON function. Here is my sample json that i am receiving from DB,
My sample json
[
{
"target":"collectd.matrix.oracle.avg_resp_time","datapoints":[[8.0, 1365158480],[null, 1365158490],[null, 1365158500],[null, 1365158510],[null, 1365158520],[null,1365158530],[8.0, 1365158540],[null, 1365158550],[null, 1365158560],[null, 1365158570],[null, 1365158580],[null, 1365158590]]
}
]
$.getJSON("myURL", createOrderDurationChart);
On success response from $.getJSON i call function below,
I am using scala framework.
I am not getting what is wrong in code or json. I can plot this json by embedding code in simple javascript and run through html directly as sample.
Here is the sample code,
function createOrderDurationChart(durationMap){
//var target=durationMap[0].target;
//var jsonstr=durationMap[0].datapoints;
//alert(target);
//alert(jsonstr);
var orderDurationChart = new Highcharts.Chart({
chart: {
renderTo: "order_duration_div",
type: "column",
margin: [10, null, null, null],
//marginRight: 10,
zoomType: 'xy',
},
title: {
text: "order duration"
//y: 5
},
xAxis: {
type: "datetime",
//tickInterval: 60*1000*10
},
yAxis: {
title: {
text: "seconds"
},
startOnTick : false,
endOnTick: false
},
series: [{
name:"avg",
data: (function (){
var data = [], i;
var jsondata = [];
jsondata= durationMap[0].datapoints;
alert(jsondata)
var datapoints=JSON.parse(jsondata);
// var jsonstr=parsejson[0].datapoints;
console.log('jsotn ' + datapoints);
// var mydata = JSON.parse(jsonstr);
// alert(mydata);
// datapoints = mydata[0].datapoints;
//alert("initial:" + json[0].time + ':' + json[0].value);
for (i = 0; i < datapoints.length; i++) {
data.push({
x:datapoints[i][1],
y:datapoints[i][0]
});
console.log('x: ' + datapoints[i][1] + ', y: ' + datapoints[i][0]);
}
return data;
})
()}]
});
}
Update code after json fix,
function createOrderDurationChart(durationMap){
//var target=durationMap[0].target;
//var jsonstr=durationMap[0].datapoints;
//alert(target);
//alert(jsonstr);
var orderDurationChart = new Highcharts.Chart({
chart: {
renderTo: "order_duration_div",
type: "column",
margin: [10, null, null, null],
//marginRight: 10,
zoomType: 'xy',
},
title: {
text: "order duration"
//y: 5
},
xAxis: {
type: "datetime",
//tickInterval: 60*1000*10
},
yAxis: {
title: {
text: "seconds"
},
startOnTick : false,
endOnTick: false
},
series: [{
name:"avg",
data: (function (){
var data = [], i;
var jsondata = [];
datapoints= durationMap[0].datapoints;
console.log('jsotn ' + datapoints);
for (i = 0; i < datapoints.length; i++) {
data.push({
x:datapoints[i][1],
y:datapoints[i][0]
});
console.log('x: ' + datapoints[i][1] + ', y: ' + datapoints[i][0]);
}
return data;
})
()}]
});
}
Any suggestions most welcome.
Thanks

Highcharts Displaying same data repeatedly

Thought I'd ask for a hand in this, am currently trying to code up a highcharts javascript file to display some data I have. I have been able to display the correct number of data sets, and on the correct graphs (they go into a time or proc graph) but I have an issue where ALL the graphs are using the same name & data, regardless of which graph they are on as well. Even though when i do an alert on where they are being assigned to their object arrays, they are all individual. Really unsure of what is happening.
where an Obj is:
{
name: SERIES_NAME,
data: SERIES_DATA,
}
The output graphs, instead of having the data as follows:
Graph Data: { Obj1, Obj2, Obj3...ObjN }, Showing multiple individual series.
I have:
Graph Data: { ObjN, ObjN, ObjN...ObjN },
They are all just ObjN. Even across the two graphs. All the data/names are the same.
Also all of this code is called from within a php $(document).ready(function())
function create_highchart(TIER,ARRAYS_STRING) {
var chart;
timestamp=document.getElementById("TIMESTAMP").value;
var graph_dir = "graphs/capsim/"+timestamp+"/";
var glue_outer = "___";
var glue_inner = ":#:";
var glue_csv="^";
var i = 0;
var j = 0;
var tier_names=[];
var WL_names = [];
var CSV_data=[];
var CSVs = [];
var CSV_det=[];
var out_arrays=[];
var time_ids = ['queue','util','arrival','thruput'];
out_arrays = ARRAYS_STRING.split(glue_outer);
tier_names = out_arrays[0].split(glue_inner);
WL_names = out_arrays[1].split(glue_inner);
CSVs = out_arrays[2].split(glue_inner);
CSV_det = out_arrays[3].split(glue_inner);
WL_num = WL_names.length;
tier_names.push('Overall System');
tier_max = tier_names.length;
curr_tier_name = tier_names[TIER];
while(i<CSVs.length){
CSV_data[i]=[];
data = CSVs[i].split(glue_csv);
CSV_data[i]=data;
i=i+1;
}
i=0;
var TMP_series = {
name: '',
data: [],
}
var TIME_SERIES_DATA=[];
var PROC_SERIES_DATA=[];
var time_count=0;
var proc_count=0;
var x = [];
var y = [];
var cat = [];
var out2 = [];
var options_time={
chart: {
renderTo: 'hc_div2',
type: 'scatter',
marginRight: 130,
marginBottom: 25
},
title: {
text: 'Highcharts Demo for Graphing',
x: -20 //center
},
subtitle: {
text: 'Graph for '+curr_tier_name,
x: -20
},
yAxis: {
title: {
text: 'Performance Metrics'
},
},
tooltip: {
formatter: function() {
return '<b>'+ this.series.name +'</b><br/>'+
'X: '+this.x +' Y: '+ this.y
}
},
plotOptions: {
scatter: {
marker: {
radius: 2,
}
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
x: 10,
y: 100,
borderWidth: 0
},
series: TIME_SERIES_DATA
};
var options_proc={
chart: {
renderTo: 'hc_div1',
type: 'scatter',
marginRight: 130,
marginBottom: 25
},
title: {
text: 'Highcharts Demo for Graphing',
x: -20 //center
},
subtitle: {
text: 'Graph for '+curr_tier_name,
x: -20
},
yAxis: {
title: {
text: 'Performance Metrics'
},
},
tooltip: {
formatter: function() {
return '<b>'+ this.series.name +'</b><br/>'+
'X: '+this.x +' Y: '+ this.y
}
},
plotOptions: {
scatter: {
marker: {
radius: 2,
}
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
x: 10,
y: 100,
borderWidth: 0
},
series: PROC_SERIES_DATA
};
var i=0;
if(TIER==tier_max-1){
TIER='OVR';
};
while(i<=CSV_det.length){
csv = CSV_det[i+4];
curr_data=CSV_data[(i/5)];
csv_name = CSV_det[i+1];
csv_tier = CSV_det[i+2];
csv_wl = parseFloat(CSV_det[i+3])+1;
wl_info = '';
if(CSV_det[i+3] !='NA'){
wl_info = ' Workload: '+csv_wl;
};
var j=0;
var line = '';
if(TIER==csv_tier){
TMP_series.data = [];
TMP_series.name = csv_name+wl_info;
while(j<curr_data.length){
XY=curr_data[j].split(',');
X = parseFloat(XY[0]);
Y = parseFloat(XY[1]);
TMP_series.data.push([X,Y]);
j=j+1;
}
j=0;
csv_type=csv.split('/')[3].split('_')[0];
if($.inArray(csv_type,time_ids)==-1){
PROC_SERIES_DATA[proc_count]=[];
PROC_SERIES_DATA[proc_count]=TMP_series;
proc_count=proc_count+1;
}else{
TIME_SERIES_DATA[time_count]=[];
TIME_SERIES_DATA[time_count]=TMP_series;
time_count=time_count+1;
}
}
i=i+5;
};
var chart = new Highcharts.Chart(options_proc);
var chart = new Highcharts.Chart(options_time);
}
A quick explanation on whats going on:
Initially parsing all the data into relevant bins from the arrays string
Creating the two highcharts that wil be displayed
Scanning over the CSVs to find ones that are relevant
For ones that are, reading their Data, and adding it to a TMP_series
Once all data is read, adding the TMP_series to the relevant graph data series
Any help is greatly apprecaited!
Thanks
You need to reset TMP_series to a new object each time you generate a series. Right now you are recycling the same object, and pushing references to the same object into the series arrays. Modify the last bit of your code to read like this:
if(TIER==csv_tier){
TMP_series = {
name : csv_name+wl_info,
data : []
};
while(j<curr_data.length){
XY=curr_data[j].split(',');
X = parseFloat(XY[0]);
Y = parseFloat(XY[1]);
TMP_series.data.push([X,Y]);
j=j+1;
}
j=0;
csv_type=csv.split('/')[3].split('_')[0];
if($.inArray(csv_type,time_ids)==-1){
PROC_SERIES_DATA[proc_count]=[];
PROC_SERIES_DATA[proc_count]=TMP_series;
proc_count=proc_count+1;
}else{
TIME_SERIES_DATA[time_count]=[];
TIME_SERIES_DATA[time_count]=TMP_series;
time_count=time_count+1;
}
}
Notice how at the top of the if, I create a new object with the specified properties, and assign it to the reference TMP_series. Remember, objects are passed by reference, so when you push objects into arrays, you are pushing a reference to the object, not a copy of the object.

Categories

Resources