Javascript+Highcharts: Substituting series.data for my own - javascript

I've been doing this script for a volunteering university-site job.
Please ignore all parameters apart from wattages and schools. Those are SQL result sets that have been converted to arrays using json_encode(). Result sets have Strings as values, I believe, so both wattages and schools should be arrays of strings.
What I want to do is input my own data for the pie graph, in this case mySeries, which I build/fill up at the start and put as data later.
function createPieChartGradient(data,title,xlabel,ylabel,type,step,div_id,wattages,schools){
var float_watt = new Array();
for(var index = 0; index < wattages.length; index++)
{
float_watt[index] = parseFloat(wattages[index]).toFixed(2);
}
var mySeries = []; //Hopefully this creates a [String, number] array that can be used as Data.
for (var i = 0; i < float_watt.length; i++) {
mySeries.push([schools[i], float_watt[i]]);
}
var options = {
chart: {
renderTo: 'graph',
zoomType: 'x',
defaultSeriesType: type
},
title: {
text: 'Consumption Percentage of IHU Schools, Last 7 days'
},
tooltip: {
//pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
},
xAxis: {
categories: [],
tickPixelInterval: 150,
// maxZoom: 20 * 1000,
title: {
style: {
fontSize: '14px'
},
text: xlabel
},
labels: {
rotation: -45,
step: step,
align: 'right'//,
// step: temp
}
},
yAxis: {
title: {
style: {
fontSize: '14px'
},
text: ylabel
},
labels: {
align: 'right',
formatter: function() {
return parseFloat(this.value).toFixed(2);
}
},
min: 0
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'center',
floating: true,
shadow: true
},
series: [{
type: 'pie',
name: 'Consumption Percentage',
data: mySeries //Problematic line.
}] //Faculty with the smallest wattage -> Green.
}; //end of var options{} //Next: -> Yellow.
//Last -> Red.
//Draw the chart.
var chart = new Highcharts.Chart(options); //TODO: Change colours.
document.write("FINISHED");
}
The thing is, the above won't work. Since I'm not using an environment (writing in notepad++ and testing on my apache web server, via the results) I have manually aliminated the problematic line to be data: mySeries.
Any idea why that is? Aren't they the same type of array, [String, number]?
Additionally, are there any environments that will help me debug javascript programs? I'm really at my wit's end with this situation and I'd very much prefer to have an IDE tell me what's wrong, or at least point me at the right direction.

You see where you are calling "toFixed"? Let's run a small experiment:
var wattages = [2.0, 3.0];
var float_watt = new Array();
for(var index = 0; index < wattages.length; index++)
{
float_watt[index] = parseFloat(wattages[index]).toFixed(2);
}
console.log(JSON.stringify(float_watt));
The output is not what you expect:
["2.00", "3.00"]
See how it got converted to a string? If you delete the "toFixed" and let your formatter do its job, things will go just fine.
EDIT
Here's how you fix your formatter:
plotOptions: {
pie: {
dataLabels: {
formatter: function() {
return parseFloat(this.y).toFixed(2);
}
}
}
},
The yLabels formatter is doing nothing for the pie.

Related

Have an issue with JavaScript, AJAX code displaying data

I need some tips from you out there to come over a good solution on my problem with JavaScript, AJAX and JSON data. I want to fill a generic set with barcharts (I am using HighCharts) on my web page. The data is in JSON format which from the start I only used date and value as pair data set. The solution works fine of I had only one bar chart it, but I have a lot of charts on my page and I need to show all of them (up to twelve).
Now I want to adjust for displaying more than one graph. In the code below the DataMacro array works fine with the chart. It also has a hard coded ID matching a . Now I have a series of in the page like id=barchart11, id=barchar21, and so on. In the dataset I have made a tag called PanelCodeUI that I am going to use looping through the dataset. The problem is how to do that. The each-loop will now fill in all date,value for all vessels.
And further it I need to restructure the function which is displaying the barchart. The best thing would be to call a function with a data array and panelCodeUI id just replacing the name of the barchart and set in the datamacro as is. But I don’t know how to do this. The data is mixed between all vessels and I need to collect all data before sending to a function. So is the problem with AJAX and JavaScript with is asynchron. I need to ensure that it behaves correctly and fast.
Maybe I need to change my dataset, or I need to do this in several step like finding all vessel IDs then do another AJAX call to get date,value pair from a vessel and then displaying. I hope there is a way to do this with this data set and hope somebody can help me on this
Here is a bit of the JSON data set:
[
{"__type":"Demo.Entities.OilProductionLast5DaysEntity","Date":1465084800000,"Value":844,"VesselId":1,"SectorId":2,"PanelCodeUI":"21","VesselCodeUI":"21","VesselSorting":1},
{"__type":"Demo.Entities.OilProductionLast5DaysEntity","Date":1465084800000,"Value":8720,"VesselId":4,"SectorId":1,"PanelCodeUI":"11","VesselCodeUI":"12","VesselSorting":2},
{"__type":"Demo.Entities.OilProductionLast5DaysEntity","Date":1465084800000,"Value":948,"VesselId":5,"SectorId":1,"PanelCodeUI":"11","VesselCodeUI":"11","VesselSorting":1},
{"__type":"Demo.Entities.OilProductionLast5DaysEntity","Date":1465084800000,"Value":0,"VesselId":6,"SectorId":3,"PanelCodeUI":"31","VesselCodeUI":"31","VesselSorting":1},
{"__type":"Demo.Entities.OilProductionLast5DaysEntity","Date":1465171200000,"Value":2067,"VesselId":1,"SectorId":2,"PanelCodeUI":"21","VesselCodeUI":"21","VesselSorting":1}
]
And here is the JavaScript code so far:
$(function () {
var datamacro = [];
$.ajax({
type: "POST",
url: '../Services/HighChartService.asmx/GetOilProductionLast5DaysByActiveVessels',
data: '',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (seriedata) {
console.log(JSON.stringify(seriedata.d));
var productions = seriedata.d;
$.each(productions, function (index, productions) {
var yval = productions.Value;
var xval = productions.Date;
var x = [xval, yval];
datamacro.push(x);
//alert("productions Name: " + productions.Date + "\nID: " + productions.Value);
});
$(function () {
//var bchart = '#barchart' + vesselindex.toString();
// want this to be looped with generic names like #barchart11, #barchart21, #barchart31 and so on
$('#barchart11').highcharts({
chart: {
type: 'column'
},
title: {
text: 'LAST FIVE DAYS'
},
subtitle: {
text: ''
},
xAxis: {
type: "datetime",
tickInterval: 24 * 3600 * 1000,
labels: {
rotation: -45,
align: 'right'
},
dateTimeLabelFormats: { // don't display the dummy year
day: '%e. %b',
},
//crosshair: true
},
credits: {
enabled: false
},
yAxis: {
labels: {
enabled: false
},
title: {
text: null
}
},
tooltip: {
formatter: function () {
return Highcharts.dateFormat('%d/%m/%Y', new Date(this.x)) + '<br/>' + ' in barrels: ' + this.y;
}
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0
}, series: {
pointRange: 24 * 3600 * 1000, // one day
pointInterval: 3600 * 1000
}
},
series: [{
//name: '',
showInLegend: false,
data: datamacro,
dataLabels: {
enabled: true,
rotation: -90,
color: '#FFFFFF',
align: 'right',
format: '{point.y:.1f}', // one decimal
y: 10, // 10 pixels down from the top
style: {
fontSize: '13px',
fontFamily: 'Verdana, sans-serif'
}
}
}]
});
});
},
error: function (r) {
alert(r.responseText);
},
failure: function (r) {
alert(r.responseText);
}
});
});
If i understand correctly, you would like to draw a chart for each different panelCodeUI ?
If that's the case, change your code after AJAX success with that :
var productions = seriedata.d;
var listPanelCodeUI = productions.map(function(p){return p.PanelCodeUI}).filter(function(item, pos, self) {
return self.indexOf(item) == pos;
});
//listPanelCodeUI : [21,11,31]
listPanelCodeUI.sort();
listPanelCodeUI.forEach(function(e){
datamacro = [];
//Create a div for each panelCodeUI
$("body").append("<div id='barchart" + e + "'></div>");
var divId = "#barchart"+e;
//Filter productions for specific panelCodeUI
var data = productions.filter(function(p){return p.panelCodeUI === e});
data.forEach(function(d){
var yval = d.Value;
var xval = d.Date;
var x = [xval, yval];
datamacro.push(x);
});
$(function () {
$(divId).highcharts({
...
})
})
}
That's what you need to parse your data:
charts = [];
$.each(productions.map(function(el) {
return el.PanelCodeUI;
}).filter(function(el, index, arr) {
return arr.indexOf(el) === index;
}), function(index,PanelCodeUI) {
var serie = productions.filter(function(el) {
return el.PanelCodeUI === PanelCodeUI;
});
$.each(serie, function(index, production) {
datamacro.push([production.Value, production.Date]);
});
drawChart('#barchart' + PanelCodeUI, 'LAST FIVE DAYS', datamacro);
});
Also i made this helper function to create the charts:
function drawChart(containerID, chartTitle, data) {
charts.push(new Highchart.Chart({
chart: {
type: 'column',
renderTo: containerID
},
title: {
text: chartTitle
},
subtitle: {
text: ''
},
xAxis: {
type: "datetime",
tickInterval: 24 * 3600 * 1000,
labels: {
rotation: -45,
align: 'right'
},
dateTimeLabelFormats: { // don't display the dummy year
day: '%e. %b',
},
//crosshair: true
},
credits: {
enabled: false
},
yAxis: {
labels: {
enabled: false
},
title: {
text: null
}
},
tooltip: {
formatter: function() {
return Highcharts.dateFormat('%d/%m/%Y', new Date(this.x)) + '<br/>' + ' in barrels: ' + this.y;
}
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0
},
series: {
pointRange: 24 * 3600 * 1000, // one day
pointInterval: 3600 * 1000
}
},
series: [{
//name: '',
showInLegend: false,
data: data,
dataLabels: {
enabled: true,
rotation: -90,
color: '#FFFFFF',
align: 'right',
format: '{point.y:.1f}', // one decimal
y: 10, // 10 pixels down from the top
style: {
fontSize: '13px',
fontFamily: 'Verdana, sans-serif'
}
}
}]
}));
}

Customize Stacked column chart in highChart

I am trying to customize stacked column chart like this
Here i did all the remaining things but i Don't know how to give that bar lines above every column........I need that bar lines in both positive and negative axis
My code
$(document).ready(function () {
$('#div1').highcharts({
chart: { type: 'column', backgroundColor: 'transparent' },
title: { text: null },
subtitle: { text: null },
credits: {
enabled: false
},
xAxis: {
categories: categories,
labels: {
rotation: 0,
style: {
fontWeight: 'normal',
fontSize: '0.9vw',
fontFamily: 'Verdana, sans-serif',
color: "black"
}
}
},
yAxis: {
title: {
enabled: false
},
lineWidth: 0,
gridLineWidth: 1,
labels: {
enabled: true
},
// gridLineColor: 'transparent',
plotLines: [{
color: '#ddd',
width: 1,
value: 0
}],
},
plotOptions: {
series: {
stacking: 'normal'
}
},
series:seriesforSeniorUPT
});
});
});
Link
Fiddle
To elaborate on Sebastian Bochan's helpful comment, here's an updated version of your fiddle with two "dummy" series to serve as the patterned background: https://jsfiddle.net/brightmatrix/hc8rLy18/2/
A few items to note:
There are two "dummy" series: one for the positive numbers and one for the negative numbers.
Both series have showInLegend and enableMouseTracking set to false so the user cannot interact with them.
Both series have stacking set to false so they will not be part of the "real" data you want to show.
Both series have zIndex set to 0. I explain why below the code block.
The code for the "dummy" series is as follows.
// background for positive values
obj = {};
obj["name"] = 'patternFill';
obj["data"] = [120, 120];
obj["color"] = 'url(#highcharts-default-pattern-3)';
obj["grouping"] = false;
obj["zIndex"] = 0;
obj["enableMouseTracking"] = false;
obj["stacking"] = false;
obj["showInLegend"] = false;
seriesforSeniorUPT.push(obj);
// background for negative values
obj = {};
obj["name"] = 'patternFill';
obj["data"] = [-80, -80];
obj["color"] = 'url(#highcharts-default-pattern-3)';
obj["grouping"] = false;
obj["zIndex"] = 0;
obj["enableMouseTracking"] = false;
obj["stacking"] = false;
obj["showInLegend"] = false;
seriesforSeniorUPT.push(obj);
For the three "real" data series, I set zIndex to 10 to they will appear over the "dummy" series we're using for our patterend backgrounds.
For all of the series, I set grouping to false so they will appear one atop the other, not next to one another.
Here's a screenshot of the output. I hope this is helpful!

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...

How do I add commas in data values

I need to add commas in the data values to display from 123456 to 123,456. I have tried searching numerous forums and supports but I just don't understand what I need to do.
This is the current script code:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
$('#container').highcharts({
chart: {
type: 'line',
marginRight: 130,
marginBottom: 25
},
title: {
text: 'Graph Title',
x: -20 //center
},
subtitle: {
text: 'Source: Name and site www.url.com',
x: -20
},
xAxis: {
categories: ['Jul-12', 'Aug-12', 'Sep-12', 'Oct-12', 'Nov-12', 'Dec-12',
'Jan-13', 'Feb-13', 'Mar-13', 'Apr-13']
},
yAxis: {
title: {
text: 'Price'
},
plotLines: [{
value: 0,
width: 1,
color: '#7c1440'
}]
},
tooltip: {
valueSuffix: ''
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
x: -10,
y: 100,
borderWidth: 0
},
series: [{
name: 'HERC Index Value',
data: [230570, 231055, 231055, 232325, 232914, 241636, 241748, 241748, 242330, 242633]
}]
});
});
</script>
I need the 'data:' values to display as: data: [230,570, 231,055, 231,055, 232,325, 232,914, 241,636, 241,748, 241,748, 242,330, 242,633].
It seems that so far, many answers are very overly complicated.
Clarification of what your end result need is will be very helpful.
However, I am going to go out on a limb and suggest that what you need is not commas in your data values that the chart will use, but a formatted number displayed on the data label, tool tip, or axis label.
If that's the case, you can use a combination of the appropriate formatter for whichever of those areas you want to affect the display of:
http://api.highcharts.com/highcharts#tooltip.formatter
http://api.highcharts.com/highcharts#plotOptions.series.dataLabels.formatter
http://api.highcharts.com/highcharts#yAxis.labels.formatter
and the numberFormat function:
http://api.highcharts.com/highcharts#Highcharts.numberFormat%28%29
If I misunderstand your need, please clarify.
In Highcharts, your data format need to be number, not string. However, why can't you use simple format with point:
data: [230.570, 231.055, 231.055, 232.325, 232.914, 241.636, 241.748, 243.748, 242.330, 242.633]
Ant then, when displaying Highcharts, display comma instead: http://api.highcharts.com/highcharts#lang.decimalPoint
Use Array.map(), it will create a new list from another with some conditions you want.
var arr = [230570, 231055, 231055, 232325, 232914, 241636, 241748, 241748, 242330, 242633],
parsed = arr.map(function(element, index, array) {
var string = element.toString(),
part1 = string.substring(0, 3),
part2 = string.substring(3);
return part1 + "," + part2;
});
alert(parsed);
Since it is not fully supported you can also do this with a for loop, define element as arr[i] and you're done!
var arr = [230570, 231055, 231055, 232325, 232914, 241636, 241748, 241748, 242330, 242633],
parsed = [];
for(var i = 0; i < arr.length; i++) {
var string = arr[i].toString();
part1 = string.substring(0, 3),
part2 = string.substring(3);
parsed.push(part1 + "," + part2);
}
alert(parsed);
The modified data will look like this:
var data = [230570, 231055, 231055, 232325, 232914, 241636, 241748, 241748, 242330, 242633],
parsed = data.map(function (element, index, array) {
var string = element.toString(),
part1 = string.substring(0, 3),
part2 = string.substring(3);
return part1 + "," + part2;
}),
obj = {
chart: {
type: 'line',
marginRight: 130,
marginBottom: 25
},
title: {
text: 'Graph Title',
x: -20 //center
},
subtitle: {
text: 'Source: Name and site www.url.com',
x: -20
},
xAxis: {
categories: ['Jul-12', 'Aug-12', 'Sep-12', 'Oct-12', 'Nov-12', 'Dec-12',
'Jan-13', 'Feb-13', 'Mar-13', 'Apr-13']
},
yAxis: {
title: {
text: 'Price'
},
plotLines: [{
value: 0,
width: 1,
color: '#7c1440'
}]
},
tooltip: {
valueSuffix: ''
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
x: -10,
y: 100,
borderWidth: 0
},
series: [{
name: 'HERC Index Value',
data: parsed
}]
};
$('#container').highcharts(obj);
Remember that parsed will be an array of strings, because commas in lists are used to define new elements!

jqplot bargraph not displaying data

Not getting any errors from firebug. Not showing in any browser. Was working previously and stopped working about a week ago. Sample of the code...
$(document).ready(function () {
//Generic names for multiple graphs
var First = $('#hfFirstOrder').val().split(",");
var Second = $('#hfSecondOrder').val().split(",");
var Third = $('#hfThirdOrder').val().split(",");
var ticks = $('#hfDaysOrder').val().split(",");
var maxValue = parseInt($('#hfMaxOrder').val());
var FirstArray = [];
var SecondArray = [];
var ThirdArray = [];
for (i = 0; i < First.length; i++) {
FirstArray.push(parseInt(First[i]));
SecondArray.push(parseInt(Second[i]));
ThirdArray.push(parseInt(Third[i]));
}
plotGraph("stackedPurchase", [FirstArray, SecondArray, ThirdArray], true, ticks, "Orders", maxValue, '#000', "Completed",
'#00F', "Ship/Pick", '#F00', "Back Order");
function plotGraph(chartName, total, stackBool, tick, yLabel, maxValue, SC1, SL1, SC2, SL2, SC3, SL3) {
plot = $.jqplot(chartName, total, {
stackSeries: stackBool,
seriesDefaults: {
renderer:$.jqplot.BarRenderer,
rendererOptions: { barMargin: 20, barWidth: 10 },
showMarker: false,
pointLabels: { show: false }
},
axes: {
xaxis: {
label: "Days",
renderer: $.jqplot.CategoryAxisRenderer,
ticks: tick
},
yaxis: {
label: yLabel,
padMin: 0,
tickInterval: parseInt(maxValue * .1),
min: 0,
max: maxValue,
tickOptions: { formatString: '%d' }
}
},
series: [{ color: SC1, label: SL1 },
{ color: SC2, label: SL2 },
{ color: SC3, label: SL3 }
],
legend: {
show: true,
location: 'e',
placement: 'outside'
}
});
}
});
And then there's a call in the html for
<div id="stackedPurchase" style="height:450px;width:900px;" runat="server"></div>
And the various hidden values are csv strings from the code behind. According to firebug they are being passed in correctly (right formats and correct number of each variable). Judging from my coding experiences recently, its probably something obvious.
Got a partial answer, the first two graphs work now because someone else at work moved the folders that the jqplot stuff was in without informing me. Changing the address in the scripts at top fixed the problem.
But for some reason the third one isn't working.
plotGraph("graphQuote", [FirstArray, SecondArray, ThirdArray], false, ticks, "Quotes", maxValue, '#F00', "Request RFQ", '#00F', "RFQ", '#0F0', "Customer Quote");
SecondArray is all zero values, FirstArray is mostly zero and ThirdArray has a value in most of its fields. Ticks has correct dates.
Alright, found the problem. Apparently
parseInt(maxValue * .1)
gets pissy and returns 0 if maxValue is less than 10, and jqplot doesn't like 0 as a tick interval. Found a better way to do intervals and now everything works.

Categories