Highcharts data value from variable array string - javascript
Got a column called ChartData in database with a string value of 4,11,25,36,50. Trying to assign this value to a hidden variable so JS can read the value of this and put this value in the data option using high charts. I have console.log the variable and looks like its appearing as a string rather than an array when being parsed across the server side to the client side.
C# code
string str = reader["ChartData"].ToString();
string[] strList = str.Split(','); //seperate the hobbies by comma
// convert it in json
dataStr = JsonConvert.SerializeObject(strList, Formatting.None);
hiddenvariable.Value = dataStr;
JS code:
function CreateBoxPlot() {
var hv = $('#hiddenvariable').val();
alert(hv); //["40","61","65","74","77"]
var chart;
var titleText = 'Test Chart Title';
var subTitleText = 'Test Chart Subtitle';
var type = 'boxplot';
var data = hv;
console.log(data); //["40","61","65","74","77"]
$(function () {
$('#container').highcharts({
chart: { type: type, inverted: true },
title: { text: titleText },
subtitle: { text: subTitleText },
legend: { enabled: false },
tooltip: {
shared: true,
crosshairs: true
},
plotOptions: {
series: {
pointWidth: 50
}
},
xAxis: {
visible: false
},
yAxis: {
visible: true,
title: {
text: 'Values'
},
plotLines: [{
value: 80,
color: 'red',
width: 2
}]
}
});
chart = $('#container').highcharts();
chart.addSeries({ data: data });
});
}
However when i hardcode data to the below value this works. How do i format this correctly when its parsed over to the JS side:
var data = [[40,61,65,74,77]]
You have to convert the string '["40","61","65","74","77"]' to js array with numbers. To make it work on each browser you can follow this approach:
Parse the string to js array using JSON.parse()
Loop through the created array and convert each element to number:
var json = '["40","61","65","74","77"]',
dataString = JSON.parse(json),
data = [],
i;
for (i = 0; i < dataString.length; i++) {
data[i] = +dataString[i];
}
Code:
$(function() {
var json = '["40","61","65","74","77"]',
dataString = JSON.parse(json),
data = [],
i;
for (i = 0; i < dataString.length; i++) {
data[i] = +dataString[i];
}
$('#container').highcharts({
chart: {
inverted: true
},
legend: {
enabled: false
},
tooltip: {
shared: true,
crosshairs: true
},
plotOptions: {
series: {
pointWidth: 50
}
},
xAxis: {
visible: false
},
yAxis: {
visible: true,
title: {
text: 'Values'
},
plotLines: [{
value: 80,
color: 'red',
width: 2
}]
}
});
chart = $('#container').highcharts();
chart.addSeries({
data: data
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container"></div>
Demo:
https://jsfiddle.net/BlackLabel/ay1xmgoc/
Taking reference from the comments, add this to your code and then try.
var data = hv.map(function (element) {
return +element;
});
Related
Create Pie chart for each Json object
I have one Json with multiple array and foreach array I want to create Pie chart, but I don't know how to do it. This is the array thet I have. And this is what I tried : function Pie() { $.getJSON("/Admin/Attivita/OreOggi", function (data) { console.log(data); var oreTecico = []; var oreTecico = []; var oreMalatia = []; var oreStraordinario = []; var oreInfortunio = []; var oreFerie = []; for (var i = 0; i < data.length; i++) { nomeTecnico.push(data[i].nome); oreTecico.push(data[i].odinario); oreMalatia.push(data[i].malatia); oreStraordinario.push(data[i].straordinario); oreInfortunio.push(data[i].infortunio); oreFerie.push(data[i].ferie); }; // Build the chart Highcharts.chart('zdravko', { chart: { plotBackgroundColor: null, plotBorderWidth: null, plotShadow: false, type: 'pie' }, title: { text: 'Ore segnate oggi' }, tooltip: { pointFormat: '<b>{point.name}</b>: {point.y:.1f} h.' }, accessibility: { point: { valueSuffix: '%' } }, plotOptions: { pie: { allowPointSelect: true, cursor: 'pointer', dataLabels: { enabled: false }, showInLegend: true } }, series: [{ name: nomeTecnico[0], colorByPoint: true, data: [{ name: '', y:0, sliced: true, selected: true }, { name: 'Odinario', y: oreTecico[0] }, { name: 'Malatia', y: oreMalatia[0] }, { name: 'Straordinario', y: oreStraordinario[0] }, { name: 'Infortunio', y: oreInfortunio[0] }, { name: 'Ferie', y: oreFerie[0] }] }] }); }); } It shows only the last "data". I want to make fo each array one pie. If i have 100 arrays I want 100 pies. UPDATE: I added this : data.forEach(function (el) { var chartData = [el.data1, el.data2]; var chartContainer = document.createElement('div'); document.getElementById('zdravko').append(chartContainer); Highcharts.chart(chartContainer, { series: [{ type: 'pie', data: chartData }] }); }); The chartData is array of undefined objects. Is it possible to make for or foreach inside Highcharts?
You need to use the Highcharts.chart method in a loop, for example: var data = [{ data1: 12, data2: 25 }, { data1: 67, data2: 11 }]; data.forEach(function(el) { var chartData = [el.data1, el.data2]; var chartContainer = document.createElement('div'); document.getElementById('container').append(chartContainer); Highcharts.chart(chartContainer, { series: [{ type: 'pie', data: chartData }] }); }); Live demo: http://jsfiddle.net/BlackLabel/x95pbw7j/ API Reference: https://api.highcharts.com/class-reference/Highcharts#.chart
Dynamically load in series HighCharts
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.
Highcharts bar chart wont animate
Not sure why because I have done it in the past, but I have a Highcharts bar chart and it won't animate. This is the declaration of the chart, function initializeData() { $http.get(url).success(function(ret) { $scope.jsondata = ret; var newdata = []; for (x = 0; x < 5; x++) { newdata.push({ name: setName($scope.jsondata[x].name), y: $scope.jsondata[x].data[0], color: getColor($scope.jsondata[x].data[0]) }); } $scope.chart.series[0].setData(newdata); }); mainInterval = $interval(updateData, 5000); } function updateData() { $http.get(url).success(function(ret) { $scope.jsondata = ret; console.debug("here"); for (x = 0; x < 5; x++) { $scope.chart.series[0].data[x].update({ y: $scope.jsondata[x].data[0], color: getColor($scope.jsondata[x].data[0]) }); } }); } $scope.chart = new Highcharts.Chart({ chart: { renderTo: 'container', type: 'bar', animation: true, events: { load: initializeData } }, title: { text: '' }, xAxis: { type: 'category', labels: { style: { fontSize: '11px' } } }, yAxis: { min: 0, max: 100, title: { text: 'Total Score', align: 'high' } }, legend: { enabled: false }, tooltip: { pointFormat: 'Total Score <b>{point.y:.3f}</b>' }, series: [{ name: 'Active Users', data: [], dataLabels: { enabled: true, rotation: 30, style: { fontSize: '10px', fontFamily: 'Verdana, sans-serif' }, format: '{point.y:.3f}', // one decimal } }] }); And as you can see I have animate : true, so I am not sure what is the problem here. I have this older plunker where all of the data is in separate series, but it animates fine. But this is the plunker I am working on and having trouble with. They are like identical basically. In the newer one I broke out the initialization of data into its own method, but that is the only real main difference. Some edits: So as I was saying, I have done things this way with an areaspline chart (I know it was said they work a bit different but they are set up identically). function initializeData() { $interval.cancel(mainInterval); $scope.previousPackets = ''; $http.get("https://api.myjson.com/bins/nodx").success(function(returnedData) { var newdata = []; var x = (new Date()).getTime(); for (var step = 9; step >= 0; step--) { newdata.push([x - 1000 * step, 0]); } $scope.chart.series[0].setData(newdata); }); mainInterval = $interval(updateData, 2000); } function updateData() { $http.get(url + acronym + '/latest').success(function(returnedData) { var x = (new Date()).getTime(); if ($scope.previousPackets != returnedData[0].numPackets) { $scope.chart.series[0].addPoint([x, returnedData[0].numPackets], true, true); $scope.previousPackets = returnedData[0].numPackets; } else { $scope.chart.series[0].addPoint([x, 0], true, true); } }); } $scope.chart = new Highcharts.Chart({ chart: { renderTo: 'container', type: 'areaspline', animation: Highcharts.svg, // don't animate in old IE marginRight: 10, events: { load: initializeData } }, title: { text: '' }, xAxis: { type: 'datetime', tickPixelInterval: 150 }, yAxis: { title: { text: 'Packets' }, plotLines: [{ value: 0, width: 1, color: '#d9534f' }] }, tooltip: { formatter: function() { return Highcharts.numberFormat(this.y) + ' packets<b> | </b>' + Highcharts.dateFormat('%H:%M:%S', this.x); } }, legend: { enabled: false }, exporting: { enabled: false }, series: [{ name: 'Packets', data: [] }] }); I also updated the first chunk of code with the initializeData() method and updateData() method which are seemingly identical in both different charts.
It looks like it plays an important role if you provide your data at chart initialization or after. For simplicity I refactored your code a little function initializeChart(initialData, onload) { $scope.chart = new Highcharts.Chart({ chart: { renderTo: 'container', type: 'bar', animation: true, events: { load: onload } .... series: [{ name: 'Active Users', data: initialData, dataLabels: { enabled: true, format: '{point.y:.3f}', // one decimal } }] }); } function getData(callback) { $http.get(url).success(function(ret) { $scope.jsondata = ret; var newdata = []; for (x = 0; x < 5; x++) { newdata.push([setName(ret[x].name), ret[x].data]); } callback(newdata); }); } As a result your two planks are in essense reduced to two methods below. The first initializes chart with preloaded data and the second updates data in existing chart. function readDataFirst() { getData(function(newdata) { initializeChart(newdata); }); } function initializeChartFirst() { initializeChart([], function() { getData(function(newdata) { $scope.chart.series[0].setData(newdata); }) }); } The first one animates fine while the second does not. It looks like highcharts skips animation if dataset is not initial and is treated incompatible. However if you really want to have animation in your current plant (chart first workflow) you can achieve that by initializing first serie with zeros and then with the real data. This case it will be treated as update function forceAnimationByDoubleInitialization() { getData(function(newdata) { initializeChart([]); var zerodata = newdata.map(function(item) { return [item[0], 0] }); $scope.chart.series[0].setData(zerodata); $scope.chart.series[0].setData(newdata); }); All these options are available at http://plnkr.co/edit/pZhBJoV7PmjDNRNOj2Uc
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 }
Remove starting "0" values from Highcharts series array
I have following generated JavaScript-Code to display a chart with HighCharts: <script type="text/javascript"> var highchartsOptions = Highcharts.setOptions(Highcharts.theme); var TaskChart; // Chart-Objekt var TaskDuration = new Array(); // Save starting points to javascript variables for HighCharts var startingUTC = 1288102643364; TaskDuration = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,206,216,216,206,206]; for(var i = 0; i < TaskDuration.length; i++) { if(TaskDuration[i] == 0) { TaskDuration[i] = null; } } </script> <script type="text/javascript"> $j(document).ready(function() { TaskChart = new Highcharts.Chart({ credits: { enabled: false }, chart: { renderTo: "chart01", defaultSeriesType: 'area', zoomType: 'x', spacingBottom: 250 }, title: { text: "Task Duration" }, xAxis: { type: 'datetime', dateTimeLabelFormats: { week: '%e. %b %Y' }, offset: 10, startOnTick: true, maxZoom: 7 * 24 * 3600000 // seven days }, yAxis: { title: { text: "Duration" } }, tooltip: { formatter: function() { return '<b>'+ this.series.name +'</b><br/>'; } }, plotOptions: { area: { stacking: 'normal', lineColor: '#666666', lineWidth: 1, marker: { lineWidth: 1, lineColor: '#666666' } } }, series: [ { name: 'Duration', pointStart: startingUTC, pointInterval: 24*60*60*1000, data: TaskDuration }] }); }); </script> The problem is now that I want to remove all the "0" values from the beginning of the TaskDuration series array. I try to set the values in the array to 'null': for(var i = 0; i < TaskDuration.length; i++) { if(TaskDuration[i] == 0) { TaskDuration[i] = null; } } But Highcharts still display the values in the chart. How to prevent this behavior? I also try to remove all values from the array until a value which is not "0". But with this approach the "startingUTC" is wrong. Maybe I have also to recalculate this value... Regards, Sandro
You need to remove elements not to set null, use this to remove zero element from array: var myArray=[]; for(var i = 0; i < TaskDuration.length; i++) { if(TaskDuration[i] != 0) { myArray.push(TaskDuration[i]); } } working JSfiddle
The problem is that you're using pointStart and pointInterval. PointInterval will ignore your null points and will add points to the yAxis. So, remove it. series: [{ name: 'Duration', data: TaskDuration }]