How to improve performance of Highcharts and avoid error 15 inspite of sorted data? - javascript

I am trying to create a gantt chart representation in highcharts with navigator. I get a JSON response from server (below is a typical response strucutre). In order to create a gantt chart representation I am creating a line between 2 points. Each point has a start_date and end_date and inorder to create this representation I am plotting a line between start_date and end_date of each point (which I have accomplished).
Response Structure from server
{
"took": 312,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 4115,
"max_score": 1,
"hits": [
]
},
"aggregations": {
"top-tags": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "Process1",
"doc_count": 6,
"process": {
"value": {
"1449878649000": {
"start_date": 1449878649000,
"process_initiator": "lol#surg.com",
"end_date": 1449878734000,
"total_seconds": 85
},
"1449879753000": {
"start_date": 1449879753000,
"process_initiator": "lol#surg.com",
"end_date": 1449879850000,
"total_seconds": 97
},
"1449881550000": {
"start_date": 1449881550000,
"process_initiator": "lol#surg.com",
"end_date": 1449881631000,
"total_seconds": 81
}
}
}
},
{
"key": "Process2",
"doc_count": 1,
"process": {
"value": {
"1449971262000": {
"start_date": 1449971262000,
"process_initiator": "lol#surg.com",
"end_date": 1449971266000,
"total_seconds": 4
}
}
}
}
]
}
}
}
Code also sharing a plunker demo
var app = angular.module('app', []);
app.directive('operationalhighstackstock', function() {
return {
restrict: 'E',
scope: true,
link: function postLink(scope, element, attrs) {
scope.$watch('operationHighChartsData', function(values) {
new Highcharts.StockChart(values);
});
}
};
});
//2014-11-30T18:15:25.000-08:00
app.controller('MainCtrl', ['$scope', function($scope) {
$scope.excludeValue = {
data: 0
};
$scope.isExcludeNeeded = true;
var opExcludeMinutes = 1,
AGENT_NAMES = "agent_names",
colorCodes = ["#8CC051", "#967BDC", "#5D9CEC", "#FB6E52", "#EC87BF", "#46CEAD", "#FFCE55", "#193441", "#193441", "#BEEB9F", "#E3DB9A", "#917A56"];
var setSummaryDisplay = function(e) {
if (e.min === null || e.max === null)
$scope.hideRangeSlider = true;
else
$scope.hideRangeSlider = false;
$scope.minimumSelectedValue = e.min;
$scope.maximumSelectedValue = e.max;
}
var getHichartsData = function(result) {
var tasksArr = [],
seriesArr = [],
userArr = [],
processArr = [];
var agentSeries = [],
agentData = {},
processSeries = [],
taskData = {},
idx = 0,
opProcessBucket = esResponse.aggregations["top-tags"].buckets,
seriesData = {};
var opBucketLength = opProcessBucket.length;
for (var opProcessBucketIndex = 0; opProcessBucketIndex < opBucketLength; ++opProcessBucketIndex) {
//opProcessBucket.forEach(function(processEntry) {
//if (opProcessBucket[opProcessBucketIndex]["key"] == $scope.gpDropDownTitle) {
var intervalBucket = opProcessBucket[opProcessBucketIndex]["process"]["value"], //opProcessBucket[opProcessBucketIndex]["top_tag_hits"]["hits"]["hits"],
intervalArr = [],
tasksIntervalArr = [],
opTaskidObj = {},
opTaskidIntervalObj = {},
process_name = null,
sortElementArr = [];
for (var key in intervalBucket) {
//intervalBucket.forEach(function(intervalEntry, intervalIndex) {
var intervalObj = {},
intervalObj2ndpoint = {},
processIntervalObj = {},
tintervalArr = [],
intervalIndex = 0,
start_temp = parseInt(key),
end_temp = intervalBucket[key].end_date; //start_temp = intervalBucket[key].start_date, end_temp = intervalBucket[key].end_date;
//added here since response contains null value and data load will take almost 1 date, verified with Bhavesh
$scope.currentDateTime = new Date().getTime();
if (end_temp == null)
end_temp = $scope.currentDateTime;
var st = new Date(moment(start_temp).valueOf()).getTime();
var et = new Date(moment(end_temp).valueOf()).getTime();
var duration = moment.duration(moment(et).diff(moment(st)));
var minutes = duration.asMinutes();
if (minutes > $scope.excludeValue.data && $scope.isExcludeNeeded) {
if (intervalIndex == 0 || process_name == null) {
process_name = opProcessBucket[opProcessBucketIndex]["key"];
processArr.push(opProcessBucket[opProcessBucketIndex]["key"]);
}
userArr.push(intervalBucket[key].process_initiator);
processIntervalObj["task_id"] = opProcessBucket[opProcessBucketIndex]["key"];
processIntervalObj["from"] = st;
var lFromtime = moment.utc(st).toDate();
lFromtime = moment(lFromtime).format('MM/DD/YY HH:mm');
var lTotime = moment.utc(et).toDate();
lTotime = moment(lTotime).format('MM/DD/YY HH:mm');
processIntervalObj["to"] = et;
processIntervalObj["color"] = "#FFCC4E";
processIntervalObj["fromDateString"] = lFromtime;
processIntervalObj["toDateString"] = lTotime;
processIntervalObj["process_initiator"] = intervalBucket[key].process_initiator == null ? 'Unknown' : intervalBucket[key].process_initiator;
processIntervalObj["total_seconds"] = intervalBucket[key].total_seconds;
//sortElementArr.push(intervalEntry["sort"][0]);
tasksIntervalArr.push(processIntervalObj);
}
}
opTaskidObj["name"] = process_name;
opTaskidIntervalObj["name"] = process_name;
opTaskidObj["data"] = [];
opTaskidIntervalObj["intervals"] = tasksIntervalArr;
opTaskidIntervalObj["intervals"] = tasksIntervalArr;
idx++;
if (tasksIntervalArr.length > 0) {
processSeries.push(opTaskidIntervalObj);
agentSeries.push(opTaskidObj);
}
//}
}
seriesData["title"] = "Test"; //item["key"];
var series = [];
(processSeries.reverse()).forEach(function(task, i) {
var item = {
name: task.name,
data: [],
turboThreshold: 1100000
};
(task.intervals).forEach(function(interval, j) {
item.data.push({
task_id: interval.task_id,
x: interval.from,
y: i,
from: interval.from,
to: interval.to,
color: interval.color,
fromDateString: interval.fromDateString,
toDateString: interval.toDateString,
total_seconds: interval.total_seconds,
process_initiator: interval.process_initiator
}, {
task_id: interval.task_id,
x: interval.to,
y: i,
from: interval.from,
to: interval.to,
color: interval.color,
fromDateString: interval.fromDateString,
toDateString: interval.toDateString,
total_seconds: interval.total_seconds,
process_initiator: interval.process_initiator
});
// add a null value between intervals
if (task.intervals[j + 1]) {
item.data.push([(interval.to + task.intervals[j + 1].from) / 2, null]);
}
});
series.push(item);
})
seriesData["data"] = series;
seriesData["tasks"] = processSeries;
seriesArr.push(seriesData);
return seriesArr;
}
$scope.agentSeriesData = getHichartsData(esResponse);
var tasks = $scope.agentSeriesData[0].tasks;
var seriesData = $scope.agentSeriesData[0].data;
var xAxisStepping = 1 * 3600 * 1000;
var chart = new Highcharts.StockChart({
chart: {
renderTo: 'container',
height: 600,
events: {
load: function(e) {
var max = this.xAxis[0].max;
var range = (24 * 3600 * 1000) * 7; // one day * 7
if ($scope.isInit || $scope.filterReseted) {
$scope.filterReseted = false;
this.xAxis[0].setExtremes(max - range, max);
}
setSummaryDisplay.call(this.xAxis[0], {
trigger: "navigator",
min: this.xAxis[0].min,
max: this.xAxis[0].max
});
}
}
},
title: {},
credits: {
enabled: false
},
xAxis: {
type: 'datetime',
gridLineWidth: 1,
tickInterval: xAxisStepping,
//ordinal:false,
dateTimeLabelFormats: {
month: '%b %e, %Y'
},
events: {
afterSetExtremes: setSummaryDisplay
},
minRange: 1000
},
yAxis: {
tickInterval: 1,
gridLineWidth: 1,
labels: {
enabled: false,
formatter: function() {
if (tasks[this.value]) {
return tasks[this.value].name;
}
}
},
startOnTick: false,
endOnTick: false,
title: {
text: 'Process'
}
},
animation: false,
rangeSelector: {
enabled: false
},
navigator: {
enabled: true
},
legend: {
enabled: false
},
tooltip: {
shared: false,
formatter: function() {
var str = '';
str += 'Process: ' + this.series.name + '<br>';
str += 'From: ' + Highcharts.dateFormat('%m/%d/%y %H:%M:%S', this.point.from) + '<br>';
str += 'To: ' + Highcharts.dateFormat('%m/%d/%y %H:%M:%S', this.point.to) + '<br>';
return str;
}
},
plotOptions: {
line: {
lineWidth: 10,
marker: {
enabled: false
},
dataLabels: {
enabled: false,
borderRadius: 5,
borderWidth: 1,
y: -6,
formatter: function() {
return this.series.name;
}
},
states: {
hover: {
lineWidth: 10
}
}
},
series: {
cursor: 'pointer',
animation: false,
point: {
events: {
click: function() {
$scope.selectedGuide = this.series.name;
//$scope.showTableView();
}
}
},
turboThreshold: 100000000,
dataGrouping: {
enabled: false
}
}
},
scrollbar: {
enabled: false
},
series: seriesData
});
$scope.operationHighChartsData = chart;
}]);
I have sorted data (ascending order) but I am still getting Highcharts error #15: www.highcharts.com/errors/15 errors in thousands (mostly 80k +), which is hanging the browser.
What could be the issue and how can I get rid of it and increase performance? Sharing a plunker which has code and relatively small number of errors.
Note: I am using Highstock JS v2.1.5

There are two problems with this code:
First thing you need to sort the series in ascending order of X. I did not want to debug your code on how do you construct your data so I added a simple loop in the end to sort everything.
for (var i in seriesData) {
seriesData[i].data.sort(function(a, b) {
if (a.x > b.x) {
return 1;
}
if (b.x > a.x) {
return -1;
}
return 0;
});
}
The other problem is that the data array contains in correct data because of this line
if (task.intervals[j + 1]) {
item.data.push([(interval.to + task.intervals[j + 1].from) / 2, null]);
}
so I changed it to this
// add a null value between intervals
if (task.intervals[j + 1]) {
item.data.push({
task_id: interval.task_id,
x: (interval.to + task.intervals[j + 1].from) / 2,
y: null,
from: (interval.to + task.intervals[j + 1].from) / 2,
to: (interval.to + task.intervals[j + 1].from) / 2
});
}
here is the fixed plnkr
http://plnkr.co/edit/OEMuVfTMhHNQsTYGUyuy?p=preview

Please read this link to improve highcharts performance. A few months ago Highcharts released boost.js to improve chart performance with millions of data points.

Related

Plotline (vertical line) in highcharts scatter chart

https://jsfiddle.net/7zL0v5oq/
I would like to have a plotline at today's date. The list can get quite long and in that case it helps with having an oversight. I fear it doesn't work because it is a scatter chart but I don't know what the problem is. I've searched all over the place but everything leads to plotlines, which clearly doesn't work. I would also be thankful if anyone knew, whether there was an easy way to filter my data the way I have it (standard highcharts filtering is deactivated but doesn't really help because of the static y values, so I get a huge, white space in the middle unless I filter at the edges. Thank you in advance for your help.
data = [{
"id": 1,
"release": "Software1",
"routine_failure_analysis_ended_on": null,
"sw_maintenance_releases_ended_on": "2014-04-01",
"sale_ended_on": "2013-04-01",
"security_vul_support_ended_on": "2015-04-01",
"service_contract_renewal_ended_on": null,
"svc_attach_ended_on": null,
"support_ended_on": "2018-03-31",
"updated_dates_on": "2012-10-03",
"created_at": "2018-05-04T18:53:21.301+02:00",
"updated_at": "2018-05-16T08:36:24.940+02:00"
},
{
"id": 2,
"release": "Software2",
"routine_failure_analysis_ended_on": null,
"sw_maintenance_releases_ended_on": "2019-07-24",
"sale_ended_on": "2017-07-31",
"security_vul_support_ended_on": "2020-07-24",
"service_contract_renewal_ended_on": null,
"svc_attach_ended_on": null,
"support_ended_on": "2022-07-31",
"updated_dates_on": "2015-08-14",
"created_at": "2018-05-05T04:00:44.170+02:00",
"updated_at": "2018-05-16T08:36:29.325+02:00"
},
{
"id": 3,
"release": "Software3",
"routine_failure_analysis_ended_on": null,
"sw_maintenance_releases_ended_on": "2018-03-01",
"sale_ended_on": "2017-03-01",
"security_vul_support_ended_on": "2018-12-01",
"service_contract_renewal_ended_on": null,
"svc_attach_ended_on": null,
"support_ended_on": "2022-02-28",
"updated_dates_on": "2016-09-02",
"created_at": "2018-05-05T04:00:44.401+02:00",
"updated_at": "2018-05-16T08:36:31.643+02:00"
}
];
const colors = ["#516", "#1781e3", "#25b252", "#20c997", "#ffc107", "#ff8b2e", "#dd1122"];
//Change to store y value paired to release/pid
var change = {};
//Which y values need to be displayed
var ticks = [0];
//Description of events
var sale = "Sale";
var support = "Support";
var svc = " SVC attach";
var sw = "Software maintenance";
var routine = "Routine failure analysis";
var service = "Service contract renewal";
var security = "Security vulnerability support";
//Data array for series
var high = [];
data.sort(function(a, b) {
return Date.parse(a.support_ended_on) < Date.parse(b.support_ended_on) ? 1 : -1
})
for (var i = 0; i < data.length; i++) {
var arr = [{
x: Date.parse(data[i].sale_ended_on),
y: (i + 1) * 20,
color: colors[0],
myValue: sale
},
{
x: Date.parse(data[i].sw_maintenance_releases_ended_on),
y: (i + 1) * 20,
color: colors[1],
myValue: sw
},
{
x: Date.parse(data[i].security_vul_support_ended_on),
y: (i + 1) * 20,
color: colors[2],
myValue: security
},
{
x: Date.parse(data[i].svc_attach_ended_on),
y: (i + 1) * 20,
color: colors[3],
myValue: svc
},
{
x: Date.parse(data[i].routine_failure_analysis_ended_on),
y: (i + 1) * 20,
color: colors[4],
myValue: routine
},
{
x: Date.parse(data[i].service_contract_renewal_ended_on),
y: (i + 1) * 20,
color: colors[5],
myValue: service
},
{
x: Date.parse(data[i].support_ended_on),
y: (i + 1) * 20,
color: colors[6],
myValue: support
}
];
var key, value;
line = [{
x: Date.parse(data[i].sale_ended_on),
y: (i + 1) * 20
}, {
x: Date.parse(data[i].support_ended_on),
y: (i + 1) * 20
}]
//Adding to change list, so we can add release/pid as label to y axis
key = (i + 1) * 20;
ticks.push(key);
if (data[i].pid) {
value = data[i].pid;
} else {
value = data[i].release;
}
change[key] = value;
//Expanding high (which is used for the highcharts series) with arr (all points for one pid)
if (data[i].pid) {
high.push({
label: data[i].pid,
name: data[i].pid,
type: 'scatter',
data: arr
}, {
type: 'line',
data: line,
linkedTo: ":previous"
});
} else {
high.push({
label: data[i].release,
name: data[i].release,
type: 'scatter',
data: arr,
showInLegend: false
}, {
type: 'line',
data: line,
linkedTo: ":previous"
});
}
}
Highcharts.chart("container", {
chart: {
height: data.length * 75
},
credits: {
enabled: false
},
yAxis: {
title: {
text: null
},
tickPositions: ticks,
visible: true,
labels: {
formatter: function() {
var value = change[this.value];
return value !== 'undefined' ? value : this.value;
}
}
},
xAxis: {
plotlines: [{
color: "#dd1122",
width: 2,
value: +new Date()
}],
type: 'datetime',
},
plotOptions: {
scatter: {
marker: {
symbol: 'circle',
radius: 7,
lineWidth: 2
}
},
line: {
enableMouseTracking: false,
marker: {
enabled: false
},
color: '#bbb',
lineWidth: 3
}
},
tooltip: {
formatter: function() {
var str = '<b>' + this.series.name + '</b><br/>'
if (this.point.myValue) {
str += this.point.myValue;
} else {
str += "Corrupted data!";
}
if (this.point.x < Date.parse(new Date))
return str += " ended on:<br/>" + Highcharts.dateFormat('%e %b %Y', new Date(this.x));
else
return str += " will end on:<br/>" + Highcharts.dateFormat('%e %b %Y', new Date(this.x));
},
shared: false
},
series: high
})
You have a typo, use plotLines instead of plotlines:
xAxis: {
plotLines: [{
...
}],
...
}
Live demo: https://jsfiddle.net/BlackLabel/p3u8ejtb/
API Reference: https://api.highcharts.com/highcharts/xAxis.plotLines

Why highchart returning " Typeerror : undefined variable byte "?

I am trying to draw a graph with the help of high chart and also using load event I am trying to add values after each 1 second to the graph.
In this graph I also want to show axis as Mb,Kb,,Gb data. So I am writing a function to return the byte values as Mb,Kb,Gb (for both series and tooltip)
This is my code :
// highchart options :
var series1, series2 ;
var chart = {
type: 'bar',
events: {
load: function () {
// set up the updating of the chart each second
series1 = this.series[0];
series2 = this.series[1];
setInterval(function () {
add_function();
}, 1000);//call function each 1 second
}
}
};
var tooltip = {
enabled: true,
formatter: function() { return fbytes(this.y,2);}
};
var plotOptions = {
bar: {
},
series: {
dataLabels: {
enabled: true,
formatter: function() { return fbytes(this.y,2);},
inside: true,
style: {fontWeight: 'number'}
},
pointPadding: 0,
pointWidth:38
},
column : {
grouping: true
}
};
series= [
{
name: 'old',
color: '#f9a80e',
data: [,]
},
{
name: 'new',
color: '#89897f',
data: [,]
}
];
and the load event function is :
Array.max = function (array) {
return Math.max.apply(Math, array);
};
Array.min = function (array) {
return Math.min.apply(Math, array);
};
add_function()
{
var arr[];
//getting array values here
var min_value = Array.min(arr);
var max_value = Array.max(arr);
var chart2 = $('#container').highcharts();
chart2.yAxis[0].update({max:max_value, min: 0}, true);
series1.setData([arr[0],arr[2]], true, true);
series2.setData([arr[1],arr[3]], true, true);
}
and the conversion function :
function fbytes(bytes, precision) {
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
var posttxt = 0;
if (bytes == 0) return '0 Bytes';
if (bytes < 1024) {
return Number(bytes) + " " + sizes[posttxt];
}
while( bytes >= 1024 ) {
posttxt++;
bytes = bytes / 1024;
}
return Math.round(bytes.toPrecision(precision)) + " " + sizes[posttxt];
}
my logic : i got some array values randomly and i am displaying this data on the graph .
problem facing : I didn't get this.y value inside series . When i print this value inside
series: {
dataLabels: {
enabled: true,
formatter: function() { return fbytes(this.y,2);},
inside: true,
style: {fontWeight: 'number'}
},
I am getting this.y = undefined . What is happening ?
Any mistake in the code ? Any suggestions ?
I created demo using your code and modified add_function() a little bit. Did you mean something like this?
function add_function(series1, series2) {
var chart2 = $('#container').highcharts(),
increment = 1024,
min_value,
max_value,
newVal1 = [],
newVal2 = [];
if (!series1.data.length && !series2.data.length) {
var arr = [512, 128, 1024, 0];
min_value = Array.min(arr);
max_value = Array.max(arr);
newVal1 = [arr[0], arr[2]];
newVal2 = [arr[1], arr[3]];
} else {
series1.yData.forEach(function(sEl, sInx) {
newVal1.push(sEl + increment);
});
series2.yData.forEach(function(sEl, sInx) {
newVal2.push(sEl + increment);
});
max_value = Array.max(newVal1.concat(newVal2));
}
chart2.yAxis[0].update({
max: max_value,
min: 0
}, true);
series1.setData(newVal1, true, true);
series2.setData(newVal2, true, true);
}
Example:
http://jsfiddle.net/js3g311q/

Jquery - Counting JSON objects

Im building a chart system that will show me all data entries. I retrieve my data using ajax and I loop trough the data and group the results by colors (red, blue and yellow) and then divide them by months.
I setup base objects (dateCounts_Red, dateCounts_Blue and dateCounts_Yellow) so that by default it starts all months at 0. A counter would then add when it finds a match tot he apropriate color and month.
When I output my dateCounts I get:
{"2015":{"2015-12":1,"2015-10":null,"2015-08":null,"2015-11":null}}
{"2015":{"2015-12":0,"2015-10":null}}
{"2015":{"2015-12":0,"2015-10":null}}
Here is the code I have so far:
var dateCounts_Red = {"2015":{"2015-01":0,"2015-02":0,"2015-03":0,"2015-04":0},"2015":{"2015-05":0},"2015":{"2015-06":0},"2015":{"2015-07":0},"2015":{"2015-08":0},"2015":{"2015-09":0},"2015":{"2015-10":0},"2015":{"2015-11":0},"2015":{"2015-12":0}};
var dateCounts_Blue = {"2015":{"2015-01":0,"2015-02":0,"2015-03":0,"2015-04":0},"2015":{"2015-05":0},"2015":{"2015-06":0},"2015":{"2015-07":0},"2015":{"2015-08":0},"2015":{"2015-09":0},"2015":{"2015-10":0},"2015":{"2015-11":0},"2015":{"2015-12":0}};
var dateCounts_Yellow = {"2015":{"2015-01":0,"2015-02":0,"2015-03":0,"2015-04":0},"2015":{"2015-05":0},"2015":{"2015-06":0},"2015":{"2015-07":0},"2015":{"2015-08":0},"2015":{"2015-09":0},"2015":{"2015-10":0},"2015":{"2015-11":0},"2015":{"2015-12":0}};
data.d.results.forEach(function(element) {
var date = element.created_date.slice(0, 7);
var yr = date.slice(0, 4);
var Color = element.colorvalue;
if(Color == "red") {
dateCounts_Red[yr][date]++;
}
if(Color == "blue"){
dateCounts_Blue[yr][date]++;
}
if(Color == "yellow"){
dateCounts_Yellow[yr][date]++;
}
});
Red_yr_2015_data = [dateCounts_Red['2015']['2015-01'], dateCounts_Red['2015']['2015-02'], dateCounts_Red['2015']['2015-03'], dateCounts_Red['2015']['2015-04'], dateCounts_Red['2015']['2015-05'], dateCounts_Red['2015']['2015-06'], dateCounts_Red['2015']['2015-07'], dateCounts_Red['2015']['2015-08'], dateCounts_Red['2015']['2015-09'], dateCounts_Red['2015']['2015-10'], dateCounts_Red['2015']['2015-11'], dateCounts_Red['2015']['2015-12']];
Blue_yr_2015_data = [dateCounts_Blue['2015']['2015-01'], dateCounts_Blue['2015']['2015-02'], dateCounts_Blue['2015']['2015-03'], dateCounts_Blue['2015']['2015-04'], dateCounts_Blue['2015']['2015-05'], dateCounts_Blue['2015']['2015-06'], dateCounts_Blue['2015']['2015-07'], dateCounts_Blue['2015']['2015-08'], dateCounts_Blue['2015']['2015-09'], dateCounts_Blue['2015']['2015-10'], dateCounts_Blue['2015']['2015-11'], dateCounts_Blue['2015']['2015-12']];
Yellow_yr_2015_data = [dateCounts_Yellow['2015']['2015-01'], dateCounts_Yellow['2015']['2015-02'], dateCounts_Yellow['2015']['2015-03'], dateCounts_Yellow['2015']['2015-04'], dateCounts_Yellow['2015']['2015-05'], dateCounts_Yellow['2015']['2015-06'], dateCounts_Yellow['2015']['2015-07'], dateCounts_Yellow['2015']['2015-08'], dateCounts_Yellow['2015']['2015-09'], dateCounts_Yellow['2015']['2015-10'], dateCounts_Yellow['2015']['2015-11'], dateCounts_Yellow['2015']['2015-12']];
Im currently getting the following error from my Highcharts js:
Uncaught TypeError: Cannot set property 'index' of undefined
THis is preventing the chart system to work correctly the data returned is not being returned with it's expected data.
Here a full example to the issue https://jsfiddle.net/awo5aaqb/21/
Would anyone know what im missing?
Your date count objects have major structural flaw.
When you prettify them they look like:
var dateCounts_Blue = {
"2015": {
"2015-01": 0,
"2015-02": 0,
"2015-03": 0,
"2015-04": 0
},
"2015": {
"2015-05": 0
},
"2015": {
"2015-06": 0
},
"2015": {
"2015-07": 0
},
......
Object keys must be unique so these are clearly being repeated and the compiler will over write duplicates.
Fix the pattern that breaks away from the intended pattern grouping at the beginning
var dateCounts_Red = {
"2015":
{
"2015-01":0,
"2015-02":0,
"2015-03":0,
"2015-04":0,
"2015-05":0,
"2015-06":0,
"2015-07":0,
"2015-08":0,
"2015-09":0,
"2015-10":0,
"2015-11":0,
"2015-12":0
},
};
var dateCounts_Blue = {
"2015":{
"2015-01":0,
"2015-02":0,
"2015-03":0,
"2015-04":0,
"2015-05":0,
"2015-06":0,
"2015-07":0,
"2015-08":0,
"2015-09":0,
"2015-10":0,
"2015-11":0,
"2015-12":0
}
};
var dateCounts_Yellow = {
"2015":{
"2015-01":0,
"2015-02":0,
"2015-03":0,
"2015-04":0,
"2015-05":0,
"2015-06":0,
"2015-07":0,
"2015-08":0,
"2015-09":0,
"2015-10":0,
"2015-11":0,
"2015-12":0}
};
Your data structure is flawed and such comparing values when doing the foreach loop becomes inconsistent because it compares it to multiple values, the above JSON is the fix for your problem.
Not quite codereview.stackexchange.com, but I heavily modified your javascript to make it work a bit better
$.ajax({
url: basePath,
dataType: 'json',
cache: false,
success: function(data) {
var counts = {};
data.d.results.forEach(function(element) {
// If you know it's all the same year, you could totally ignore this
var yr = element.created_date.slice(0, 4);
var month = parseInt(element.created_date.slice(5,7));
var color = element.colorvalue;
if (counts[color] === undefined) {
counts[color] = {};
}
if (counts[color][yr] === undefined) {
counts[color][yr] = {};
}
current_value = counts[color][yr][month];
if (current_value === undefined) {
// Doesnt exist yet, so add it
counts[color][yr][month] = 1;
} else {
// Exists, so increment by 1
counts[color][yr][month] = current_value + 1;
}
});
console.log(JSON.stringify(counts));
console.log(transform_series(counts['red']['2015']));
console.log(transform_series(counts['blue']['2015']));
console.log(transform_series(counts['yellow']['2015']));
var Options = {
chart: {
renderTo: 'myfirstchart',
type: 'column',
margin: 75,
options3d: {
enabled: true,
alpha: 25,
beta: 0,
depth: 70
}
},
title: {
text: "Test Highcharts"
},
subtitle: {
text: 'Test charts'
},
plotOptions: {
column: {
depth: 25
}
},
xAxis: {
categories: ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"]
},
yAxis: {
title: {
text: "Number of entries"
}
},
tooltip: {
headerFormat: '<b>{point.key}</b><br>',
pointFormat: '<span style="color:{series.color}">\u25CF</span> {series.name}: {point.y} / {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
depth: 40
}
},
series: [{
name: 'Red',
color: 'red',
data: transform_series(counts['red']['2015']),
stack: '2015'
}, {
name: 'Blue',
color: 'blue',
data: transform_series(counts['blue']['2015']),
stack: '2015'
}, {
name: 'Yellow',
color: 'yellow',
data: transform_series(counts['yellow']['2015']),
stack: '2015'
}]
};
return new Highcharts.Chart(Options);
}
});
// this transforms the hash {10: 5, 11:1, 12:1} to get you all 12 months
// and returns an array of values [ 0, 0, 0, 0, 0 ... 5, 1, 1] that
// can be used in high charts
function transform_series(series) {
return Array.apply(null, Array(13)).map(function (_, i) {return (series[i] === undefined) ? 0 : series[i];}).slice(1,13);
}

jqplot chart with data from variable and data from JSON

I'm trying to load data into a jqplot chart via variable, but it's only displaying the first value. I'm lost at to why is doing this.
JavaScript:
$(document).ready(function () {
var sin = [[20, 10, 0, 10, 15, 25, 35, 50, 48, 45, 35, 30, 15, 10]];
var plot = $.plot($(".chart"),
[{ data: sin, label: "sin(x)", color: "#ee7951" }], {
series: {
lines: { show: true },
points: { show: true }
},
grid: { hoverable: true, clickable: true },
yaxis: { min: 0, max: 60 }
});
var previousPoint = null;
$(".chart").bind("plothover", function (event, pos, item) {
if (item) {
if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex;
$('#tooltip').fadeOut(200, function () {
$(this).remove();
});
var x = item.datapoint[0].toFixed(2),
y = item.datapoint[1].toFixed(2);
maruti.flot_tooltip(item.pageX, item.pageY, item.series.label + " of " + x + " = " + y);
}
} else {
$('#tooltip').fadeOut(200, function () {
$(this).remove();
});
previousPoint = null;
}
});
});
maruti = {
flot_tooltip: function (x, y, contents) {
$('<div id="tooltip">' + contents + '</div>').css({
top: y + 5,
left: x + 5
}).appendTo("body").fadeIn(200);
}
}
</script>
Ultimately, I would prefer to use JSON format data and use the first value for the chart and the second for the axis.
Data:
[["50.00","3/18/2015 2:00:00 PM"],["37.00","3/12/2015 3:42:44 PM"],["35.00","3/11/2015 3:42:44 PM"]]
Any recommendations or link to samples using this type of data would be greatly appreciated.
The string format was wrong. I ended up using Entity Framework.
So my code behind looks something like:
using (myEntities myEntitiesContainer = new myEntities())
{
var alldata = myEntitiesContainer.myData(id).ToList();
foreach (myData i in alldata)
{
if (alldata.IndexOf(i) == alldata.Count - 1)
{
sb.Append("['").Append(i.DateData.ToString("yyyy-MM-dd HH:mmtt")).Append("', ").Append(i.SomeData.ToString()).Append("]");
}
else
{
sb.Append("['").Append(i.DateData.ToString("yyyy-MM-dd HH:mmtt")).Append("', ").Append(i.SomeData.ToString()).Append("], ");
}
}
myReturnString = sb.ToString();
}
The return string:
[['2015-03-31 16:00PM', 30.00], ['2015-03-31 14:00PM', 40.00], ['2015-03-31 13:00PM', 50.00]]
The Javascript looks like:
var renderGraph = function () {
var plot
var line1 =
plot = $.jqplot('chart', [line1], {
axes: {
xaxis: {
renderer: $.jqplot.DateAxisRenderer,
tickOptions: { min: 0, formatString: '%b %#d' },
tickInterval: '1 day'
},
yaxis: {
tickOptions:{ formatString: '%d'}
}
},
highlighter: {
show: true,
yvalues: 1,
xvalues: 1,
formatString: 'Date: %s Level: %s'
},
cursor: {
show: false,
tooltipLocation: 'sw'
},
legend: {
show: false
}
});
}

Highcharts : yAxis, values rounded to a maximum of two decimal places

The code of my graph is this (take data from a php page and then adds some series):
$('#grafico_1').highcharts({
chart: {
type: 'line',
zoomType: 'xy',
animation : false,
events: {
selection: function(event) {
if(event.resetSelection){
setTimeout(function(e){
var chart = $('#grafico_1').highcharts();
var extreme = chart.yAxis[0].getExtremes();
var mio_min = parseFloat(proprieta_temperatura_aperto[34]);
var mio_max = parseFloat(proprieta_temperatura_aperto[35]);
if(extreme.dataMin < mio_min){
mio_min = extreme.dataMin;
}
if(extreme.dataMax > mio_max){
mio_max = extreme.dataMax;
}
chart.yAxis[0].setExtremes(mio_min,mio_max);
$("#temperatura_min_max_rilevato").html("Min "+extreme.dataMin+"°C - Max "+extreme.dataMax+"°C");
//console.log("zoom - ");
}, 10);
}else{
setTimeout(function(e){
var chart = $('#grafico_1').highcharts();
var extreme = chart.yAxis[0].getExtremes();
$("#temperatura_min_max_rilevato").html("Min "+extreme.dataMin+"°C - Max "+extreme.dataMax+"°C");
//console.log("zoom + "+JSON.stringify(extreme));
}, 50);
}
}
},
},
credits : {
enabled : false
},
title: {
text: 'Grafico di Oggi'
},
xAxis: {
type: 'datetime',
title: {
text: false
}
},
yAxis: [
{
title: {
text: false
},
labels: {
format: '{value}°C',
},
//ceiling : parseFloat(proprieta_temperatura_aperto[35]),
//floor: parseFloat(proprieta_temperatura_aperto[34]),
max : parseFloat(proprieta_temperatura_aperto[35]),
min: parseFloat(proprieta_temperatura_aperto[34]),
},
{
title: {
text: false
},
min: 0,
max : 1,
ceiling:1,
floor : 0,
//tickLength : 1,
opposite: true,
tickInterval: 1,
labels: {
formatter: function() {
if (this.value == 0 || this.value == 1){
return this.value;
}else{
return null;
}
}
}
}
],
tooltip: {
formatter: function() {
var s = '<b>Data</b> '+Highcharts.dateFormat('%H:%M:%S', this.x) + '<br><b>Temperatura</b> ' + this.y + '°C<br/>';
$.each(this.points, function(i, point) {
if(point.series.name != "Temperatura"){
s += '<b>' + point.series.name +'</b> : '+ point.y + '<br>';
}
});
return s;
},
shared: true,
backgroundColor: '#FCFFC5'
},
plotOptions: {
line : {
turboThreshold: 0,
},
series: {
animation: false,
marker: {
enabled: false
}
}
},
series: []
});
the problem occurs when run one (or more) zoom on the graphs , and on the y-axis the values ​​are listed with more than two decimal places. I would like to limit to two the maximum number of decimal places.
I think i have to change this field (format)
yAxis: [
{
labels: {
format: '{value}°C',
},
but I do not know how.
Try to write the value as {value:.2f}, as proposed here: link

Categories

Resources