dynamically creating the values for high charts - javascript

I want to create dynamic data for high charts,
i need to generate dynamic values in the x-axis
xAxis: {
categories:['project1','project2']
},
This is my for loop,
var project = [];
for(var i=0;i<project.name;i++){
//new array
}
How do i create dynamic values in the x-axis.

You can pass an array variabile as parameter to the categories option of the chart.
Example:
// Original array
var categories1=['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
// Copy and/or modifify the second array content and do some stuff
var categories2=[];
for(var i=0;i<categories1.length;i++){
categories2.push(categories1[i]);
}
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container'
},
xAxis: {
categories: categories2 // reference categories to an array variabile
},
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}]
});
Working fiddle: http://jsfiddle.net/IrvinDominin/6c8Af/

Another approach:
var Series2 = [1,1,1,2,2,2];
var names=['O','A'];
var data1=Series2,seriesArray; //seriesArray is formed dynamically - array of int values
options.series = [{name: names, data: data1}]
This works properly

I'm using a JSON data and after a long time able to resolve it. My requirement was to get JSON data and then I create a Map Object based on my data requirement. And dynamically create series for chart. I was able to create Series but nothing was coming in chart.
This was because the numeric digits has to be converted to Int . When I used parseInt, it worked for me.
Step 1: I get the JSON data and after manipulation it looks like this: seriesData = {"O":series1}, {"A":Series2}, {"S":Series3}]
var options = {
chart: {
renderTo: 'demoGraph',
type: 'column'
},
title: {
text: 'Stacked column chart'
},
xAxis: {
categories: [1, 2, 3, 4, 5,6],
title: {
text: 'Severity'
},
},
yAxis: {
min: 0,
title: {
text: 'Total Defects with Severity - 1,2,3,4,5,6'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
}
},
legend: {
align: 'right',
x: -70,
verticalAlign: 'top',
y: 20,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false
},
tooltip: {
formatter: function () {
return '<b>' + this.x + '</b><br/>' +
this.series.name + ': ' + this.y + '<br/>' +
'Total: ' + this.point.stackTotal;
}
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white',
style: {
textShadow: '0 0 3px black, 0 0 3px black'
}
}
}
},
series: [{},{},{},{},{},{}],
};
for(var i in seriesData ){
for(var j in seriesData [i]){
options.series[i].name = j;
options.series[i].data = seriesData [i][j];
break;
}
}
var chart = new Highcharts.Chart(options);

Related

Highcarts - Update a specific categorys values

In a laravel project, I'm using Highcharts to show a chart of the standard column type simply called column. xAxis has 4 categories representing teams, and yAxis holds each teams score. It looks like this:
<div id="chart" style="min-width: 310px; height: 400px; margin: 0 auto"></div>
<script type="text/javascript">
var chart1 = Highcharts.chart('chart', {
chart: {
type: 'column'
},
title: {
text: 'title'
},
xAxis: {
categories: ["f","j","n","s"]
},
yAxis: {
min: 0,
title: {
text: 'Total score'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
}
},
legend: {
align: 'right',
x: -30,
verticalAlign: 'top',
y: 25,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}<br/>Total: {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
}
}
},
});
</script>
The points are added after the page is loaded by using jquery and a javascript function like so:
$( document ).ready(function() {
#foreach($existingScores as $score)
addScoreToChart({!! $score !!})
#endforeach
});
function addScoreToChart(obj)
{
var scores = obj.params.scores;
var datas = [];
for(var k in scores){
datas.push([k, parseInt(scores[k])]);
}
console.log(datas);
chart1.addSeries({
name: obj.clientName,
data: datas,
});
}
This works fine on the initial load of the scores. Some scores will be added to the chart after the page is loaded (via websockets).
I'm quite unsure how to actually update a given teams score. The websockets part is working, and when a new score is added i can call a javascript function that updates the scoreboard with the new data. How can i do this ? Say for example that a new score of 5 points for team "j" is added. How would i tell Highcharts to update the chart with such data / add 5 points to "j" existing score?
You can use series.update to update a series, this function will merge the input with the existing series. Can be done like this:
function updateTeam(obj) {
let name = obj.params.name;
let scores = obj.params.scores;
let datas = [];
for (let k in scores) {
datas.push([parseInt(k), parseInt(scores[k])]);
}
let tmpSeries = chart.series;
for (var i = 0; i < tmpSeries.length; i++) {
if (tmpSeries[i].name == name ) {
tmpSeries[i].update({
data: datas
}, true);
}
}
}
var chart = Highcharts.chart('container', {
chart: {
type: 'column'
},
title: {
text: 'title'
},
xAxis: {
categories: ["f", "j", "n", "s"]
},
yAxis: {
min: 0,
title: {
text: 'Total score'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
}
},
legend: {
align: 'right',
x: -30,
verticalAlign: 'top',
y: 25,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}<br/>Total: {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
}
}
},
series: [{
name: 'team1',
data: [29.9, 71.5, 106.4, 129.2]
},
{
name: 'team2',
data: [29.9, 71.5, 106.4, 129.2]
}, {
name: 'team3',
data: [29.9, 71.5, 106.4, 129.2]
}
]
});
function updateTeam(obj) {
let name = obj.params.name;
let scores = obj.params.scores;
let datas = [];
for (let k in scores) {
datas.push([parseInt(k), parseInt(scores[k])]);
}
let tmpSeries = chart.series;
for (var i = 0; i < tmpSeries.length; i++) {
if (tmpSeries[i].name == name ) {
tmpSeries[i].update({
data: datas
}, true);
}
}
}
// the button handler
$('#button').click(function() {
var incomingObj = {
params: {
name: 'team1',
scores: [2.1, 5.6, 150.4, 99.9]
}
};
updateTeam(incomingObj);
});
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div id="container" style="height: 400px"></div>
<button id="button" class="autocompare">Update Series</button>
Working JSfiddle: http://jsfiddle.net/ewolden/Lrxu5u68/2/
You will need to redraw the chart as far as I can remember highcharts wont watch the data to draw.
Call chart.redraw() when new data comes in from your web socket.

HighCharts Custom SVG Marker Symbol

Based on the Highcharts documentation you can create your own point marker by defining a custom callback for an (SVG-based) symbol path.
However, what if you need to get at the underlying series data from within the symbol prototype function? Is that possible?
For instance:
Highcharts.SVGRenderer.prototype.symbols.cross = function (x, y, w, h) {
// I want to be able to access the series data from here.
// Either the point data or the entire series' data array.
return ['M', x, y, 'L', x + w, y + h, 'M', x + w, y, 'L', x, y + h, 'z'];
};
if (Highcharts.VMLRenderer) {
Highcharts.VMLRenderer.prototype.symbols.cross = Highcharts.SVGRenderer.prototype.symbols.cross;
}
Highcharts.chart('container', {
title: {
text: 'Demo of predefined, image and custom marker symbols'
},
legend: {
y: -40 // make room for subtitle
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
series: [{
name: 'Custom symbol',
data: [54.4, 29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6],
marker: {
symbol: 'cross',
lineColor: null,
lineWidth: 2
}
}],
credits: {
enabled: false
},
subtitle: {
text: '*) Base64 not supported in IE6 and IE7',
verticalAlign: 'bottom',
align: 'right',
y: null,
style: {
fontSize: '10px'
}
}
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div id="container" style="height: 400px; max-width: 800px; margin: 0 auto"></div>
Turns out, you can actually define the marker properties at the individual point level. From there, you can provide the value and make it accessible from within the custom callback.
Like so:
Highcharts.SVGRenderer.prototype.symbols.cross = function(x, y, w, h, d) {
// I want to be able to access the series data from here.
// Either the point data or the entire series' data array.
if (d.v) {
console.debug("Point-specific data: " + d.v);
}
// From here, you can imagine one can use the point-specific data to affect the symbol path.
// A good example would be to in case you want to build a series of custom wind barbs,
// in which the path of the barb will be based on the intensity and direction of each point
// ...
return ['M', x, y, 'L', x + w, y + h, 'M', x + w, y, 'L', x, y + h, 'z'];
};
if (Highcharts.VMLRenderer) {
Highcharts.VMLRenderer.prototype.symbols.cross = Highcharts.SVGRenderer.prototype.symbols.cross;
}
Highcharts.chart('container', {
title: {
text: 'Demo of predefined, image and custom marker symbols'
},
xAxis: {
type: 'datetime'
},
series: [{
name: 'Custom symbol',
data: [{
x: 1525089600000,
y: 54.4,
marker: {
symbol: "cross",
v: 54.4
}
},
{
x: 1525090500000,
y: 71.5,
marker: {
symbol: "cross",
v: 71.5
}
},
{
x: 1525091400000,
y: 29.9,
marker: {
symbol: "cross",
v: 29.9
}
}
],
marker: {
symbol: 'cross',
lineColor: null,
lineWidth: 2
}
}],
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container" style="height: 400px"></div>

HighCharts column unknown number of series

I'm trying to populate a HighCharts dataset with results from SQL Server in Classic ASP.
When the number of series is known everything work OK but I can't get it work correctly for unknown number of series.
Here is my code for 4 series - 1 line and 3 columns.
<script type="text/javascript">
$(function () {
var DivName1 = '<%= DivName(1)%>'
var DivName2 = '<%= DivName(2)%>'
var DivName3 = '<%= DivName(3)%>'
var DivName4 = '<%= DivName(4)%>'
var DivN1 = parseInt('<%= DivN(1)%>')
var DivN2 = parseInt('<%= DivN(2)%>')
var DivN3 = parseInt('<%= DivN(3)%>')
var DivN4 = parseInt('<%= DivN(4)%>')
var DivTotal1 = parseFloat('<%= DivTotal(1)%>')
var DivTotal2 = parseFloat('<%= DivTotal(2)%>')
var DivTotal3 = parseFloat('<%= DivTotal(3)%>')
var DivTotal4 = parseFloat('<%= DivTotal(4)%>')
$('#DivCompTotalA').highcharts({
chart: {
type: 'column'
},
title: {
text: ''
},
credits: {
enabled: false
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
itemWidth: 180,
useHTML: true,
x: 0,
y: 40,
borderWidth: 0
},
xAxis: {
categories: ['']
},
yAxis: {
max: 7.01,
labels: {
enabled: false
},
gridLineColor: 'transparent',
plotLines: [{
value: DivTotal1,
color: '#333333',
width: 2,
label: {
text: 'Org.=' + DivTotal1 + '<br>N=' + DivN1,
align: 'right',
y: -5,
x: 0,
style: {
fontSize: '13px'
}
},
zIndex: 2
}],
title: {
text: ''
}
},
plotOptions: {
column: {
pointPadding: 0.2,
groupPadding: 0.10,
borderWidth: 0
},
series: {
dataLabels: {
enabled: true,
y: 5,
style: {
fontSize: '14px'
}
},
enableMouseTracking: false,
events: {
legendItemClick: function () {
return false;
}
}
}
},
series: [{
name: DivName2 + ' [' + DivN2 + ']',
color: '#c9e7ff',
data: [DivTotal2]
}, {
name: DivName3 + ' [' + DivN3 + ']',
color: '#4898a4',
data: [DivTotal3]
}, {
name: DivName4 + ' [' + DivN4 + ']',
color: '#ffd949',
data: [DivTotal4]
}]
});
});
My first question is How to replace these lines:
var DivName1 = '<%= DivName(1)%>'
var DivName2 = '<%= DivName(2)%>'
var DivName3 = '<%= DivName(3)%>'
var DivName4 = '<%= DivName(4)%>'
with a loop I tried this loop but with no success
var N = '<%=N %>'
var DivName = []
for (var i = 0; i <= N; i++) {
DivName[i] = '<%= DivName(i)%>';
}
How to write the "i" inside the '<%= DivName(i)%>' so it will be a variant
Try something like this:
Set series to nothing:
series: []
Fill it by script (where seriesData is array of prepared data. For format check documentation
$.each(Div, function(i){
var chart = $('#container').highcharts();
if (chart.series.length === 1) {
chart.addSeries({
name: Div[i].Name + i + ' [' + Div[i].N + ']',
color: '#c9e7ff',
data: Div[i].Total
});
}
});
Here an example how to add 1 series. You can add as many as you like with each loop.
$(function () {
$('#container').highcharts({
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}]
});
// the button handler
$('#button').click(function () {
var chart = $('#container').highcharts();
if (chart.series.length === 1) {
chart.addSeries({
data: [194.1, 95.6, 54.4, 29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4]
});
}
});
});

Highcharts disable click on column

I have a column chart. When clicking one of the vertical bars, the color of the selected bar changes. I want to disable this behaviour by disabling the detection of the 'click' event on the graph so when the user clicks there nothing happens.
Anyone knows how to do that?
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'column',
backgroundColor: 'transparent',
container: {
onclick : null
}
},
colors: ['#27A1DE'],
title: {
text: null
},
credits : {
enabled: false
},
exporting : {
enabled: false
},
legend: {
enabled: false
},
xAxis: {
title: {
text: 'h',
align: 'high',
offset: -15
},
tickColor : 'transparent',
labels: {
style: {
fontWeight:'bold'
},
y: 12,
formatter: function() {
var index = this.axis.categories.indexOf(this.value);
var yValue = this.chart.series[0].yData[index];
if (yValue === 0){
return '<span>'+this.value+'</span>';
} else {
return '<span style="color:#009DE0;">'+this.value +'</span>';
}
}
},
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
yAxis: {
min: 0,
labels: {
enabled: false
},
gridLineWidth: 0,
lineWidth: 1,
title: {
align: 'high',
rotation: 0,
text: 'kWh',
offset: 0,
y: -2
}
},
plotOptions: {
column: {
pointPadding: 0.05,
groupPadding: 0,
dataLabels : {
enabled: true,
crop :false,
overflow: 'none',
rotation: 270,
x:2,
y:-14,
style: {
color: '#009DE0',
fontSize: 'xx-small',
},
formatter: function() {
if (this.y != 0){
return '<span>'+this.y +'</span>';
} else {
return '<span style="display:none;">'+this.y +'</span>';
}
}
},
borderWidth: 0,
events: {
click: function(e){
//this.update({ color: '#27a1de' }, true, false);
e.preventDefault();
return false;
}
}
},
series: {
cursor: 'pointer',
point: {
events: {
click: function() {
}
}
}
}
},
series: [{
name: '',
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}],
tooltip: {
enabled: false
}
});
Fiddle : here
Thanks
the way I understood your problem, you want to remove the style change on mouse hover (as there is no color change on click in your fiddle unlike you described).
http://jsfiddle.net/6pur4o1w/
states: { hover: 'none' }
in the series should do what you want.

Howto move dataLabels to the border of the plot area?

I have a bar chart. I want the dataLabels to not stick onto the bars, but move it to the most right border of the plot area and have it text-aligned right.
This is what I have come to so far: (jsfiddle)
$(function () {
var cat = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug']; //, 'Sep', 'Oct', 'Nov', 'Dec', 'foo', 'bar', 'bla'];
var barWidth = 16;
chart = new Highcharts.Chart({
chart: {
type: "bar",
renderTo: 'container',
events: {
load: function() {
var plotHeight = this.plotHeight;
console.log('plotHeight = ' + plotHeight);
var catWidth = (barWidth-2) / (2*plotHeight/cat.length);
var plot = [];
for(var i=0; i<(cat.length); i+=1) {
var newPlot = {
color: 'grey',
width: 1,
value: i+catWidth //+(cat.length/($('#container').height()/10))
};
plot.push(newPlot);
this.xAxis[0].addPlotLine(newPlot);
}
//this.xAxis[0].addPlotLine(plot);
}
}
},
title: {
text: null
},
credits: {
text: null,
enabled: false
},
xAxis: {
categories: cat,
title: {
text: null,
enabled: false
}
},
yAxis: {
title: {
text: null,
enabled: false
},
labels: {
enabled: false
},
gridLineWidth: 0,
gridLineColor: 'none'
},
plotOptions: {
series: {
dataLabels: {
enabled: true,
color: '#000',
formatter: function() {
return Math.abs(this.y).toFixed(1) + '%';
},
crop: false, // DIRTY!!! :(
overflow: 'justify', // DIRTY!!! :(
x: -360 // DIRTY!!! :(
}
}
},
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5], //, 216.4, 194.1, 95.6, 54.4, 9.9, 9.9, 9.9],
pointWidth: barWidth
}]
});
});
I have to stick at mostly native Highcharts as I need to export the chart as svg to reuse in a pdf file. So using CSS and useHtml: true are out of question as well as dirty hacks like crop: false, overflow: 'justify', dataLabels.x: -360 (just to show you what I want to do - although it is not right aligned).
How am I able to accomplish that?
You can use workaround with the translating datalables like here:
var width = chart.plotWidth;
$.each(chart.series[0].data, function(i,d){
var bbox = d.dataLabel.getBBox().width;
d.dataLabel.attr({
x: width - bbox
});
});
http://jsfiddle.net/9YyVJ/2/

Categories