Highcharts series setData from ajax php procedure - javascript

I am using Highcharts on my website. Then an Ajax PHP procedure to load data dynamically from database, by clicking on a legend item. Now I want to set the result into the series data but with no success as I am unable to use 'this' as 'this' is not the legend item anymore. You'll be able to understand it from the code below. I tried something like chart.series.setData[] but it did not work. Thanks for any solutions of how can I proceed.
<script>
Highcharts.chart('myChart', {
series: [<?echo $allnames;?>],
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top'
},
plotOptions: {
series: {
events: {
legendItemClick: function() {
var jmeno=this.name;
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
myData= this.responseText;
//I am unable to use 'this' as it is not the legend item
this.setData([myData]);
}
};
xmlhttp.open("GET","/data.php?q="+jmeno,true);
xmlhttp.send();
}
}
}
},
});
</script>

Resolved.
<script>
Highcharts.chart('graf', {
title: {text: 'Hello darkness my old friend'},
series: [<?echo $allnames;?>],
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top'
},
plotOptions: {
series: {
events: {
legendItemClick: function() {
var jmeno=this.name;
var that=this;
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var myData = this.responseText;
var splitData = myData.split(",");
var newData = [];
for(var i = 0;i<splitData.length;i++){
var num = splitData[i];
if(num != ""){
num = parseFloat(num);
newData.push(num);
}
}
that.setData(newData);
}
};
xmlhttp.open("GET","/data.php?q="+jmeno,true);
xmlhttp.send();
}
}
}
},
});
</script>

Related

Can I make a graph between two xhttp variables?

I tried to make a graph between two variables instead of graphinh time but I couldn't. So I want to know I this is available by the way?
var chartT = new Highcharts.Chart({
chart: { renderTo: "chart-temperature" },
title: { text: "DHT22 Temperature" },
series: [
{
showInLegend: false,
data: [],
},
],
plotOptions: {
line: { animation: false, dataLabels: { enabled: true } },
series: { color: "#059e8a" },
},
xAxis: { type: "datetime", dateTimeLabelFormats: { second: "%H:%M:%S" } },
yAxis: {
title: { text: "Temperature (Celsius)" },
//title: { text: 'Temperature (Fahrenheit)' }
},
credits: { enabled: false },
});
setInterval(function () {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var x = new Date().getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if (chartT.series[0].data.length > 40) {
chartT.series[0].addPoint([x, y], true, true, true);
} else {
chartT.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open("GET", "/temperature", true);
xhttp.send();
}, 30000);
var chartH = new Highcharts.Chart({
chart: { renderTo: "chart-humidity" },
title: { text: "DHT22 Humidity" },
series: [
{
showInLegend: false,
data: [],
},
],
plotOptions: {
line: { animation: false, dataLabels: { enabled: true } },
},
xAxis: {
type: "datetime",
dateTimeLabelFormats: { second: "%H:%M:%S" },
},
yAxis: {
title: { text: "Humidity (%)" },
},
credits: { enabled: false },
});
setInterval(function () {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var x = new Date().getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if (chartH.series[0].data.length > 40) {
chartH.series[0].addPoint([x, y], true, true, true);
} else {
chartH.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open("GET", "/humidity", true);
xhttp.send();
}, 30000);
I wanted to make a graph between humidity on y axis and temperature on x axis. I tried changing the x variable ,of the humidity chart, to be like the y variable ,of the temperature chart, but the chart of the humidity didn't work.
You have to synchronize the received data from the two API requests. Here's a solution that records partial data (either temperature or humidity) - pending array and identifies corresponding requests by registering the time of the requested - tRequest.
This may be a starting point for your more elaborate solution. Please let me know if this is not exactly what you wanted.
The data is simulated (random points) as I don't have access to your API, but there are real XMLHttpRequests (to highcharts on cdn).
The same in this fiddle
var chartT = new Highcharts.Chart({
chart: { renderTo: "chart-temperature" },
title: { text: "DHT22 Temperature" },
series: [
{
showInLegend: false,
data: [],
},
],
plotOptions: {
line: { animation: false, dataLabels: { enabled: true } },
series: { color: "#059e8a" },
},
xAxis: { type: "datetime", dateTimeLabelFormats: { second: "%H:%M:%S" } },
yAxis: {
title: { text: "Temperature (Celsius)" },
//title: { text: 'Temperature (Fahrenheit)' }
},
credits: { enabled: false },
});
var chartH = new Highcharts.Chart({
chart: { renderTo: "chart-humidity" },
title: { text: "DHT22 Humidity" },
series: [
{
showInLegend: false,
data: [],
},
],
plotOptions: {
line: { animation: false, dataLabels: { enabled: true } },
},
xAxis: {
type: "datetime",
dateTimeLabelFormats: { second: "%H:%M:%S" },
},
yAxis: {
title: { text: "Humidity (%)" },
},
credits: { enabled: false },
});
var chartTH = new Highcharts.Chart({
chart: { renderTo: "chart-temperature-humidity", type: "scatter" },
title: { text: "DHT22 Humidity vs Temperature" },
series: [
{
showInLegend: false,
data: [],
},
],
plotOptions: {
//line: { animation: false, dataLabels: { enabled: true } },
scatter: {marker: {fillColor: '#ce4a05'}}
},
xAxis: {
title: { text: "Temperature (Celsius)" },
},
yAxis: {
title: { text: "Humidity (%)" },
},
credits: { enabled: false },
});
function requestTemperature(whenReceived) { // whenReceived is a handler to be called when a data point was received
var tRequest = new Date().getTime();
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var x = new Date().getTime(),
y = Math.floor(Math.random()*100)/4;//parseFloat(this.responseText);
whenReceived(x, y, tRequest);
}
};
xhttp.open("GET", "https://cdnjs.cloudflare.com/ajax/libs/highcharts/10.3.2/highcharts.js", true);
xhttp.send();
}
function requestHumidity(whenReceived) {
var tRequest = new Date().getTime();
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var x = new Date().getTime(),
y = Math.floor(100+Math.random()*250)/4;//parseFloat(this.responseText);
whenReceived(x, y, tRequest);
}
};
xhttp.open("GET", "https://cdnjs.cloudflare.com/ajax/libs/highcharts/10.3.2/highcharts.js", true);
xhttp.send();
}
function addToChart(chart, [x, y]){
if (chart.series[0].data.length > 40) {
chart.series[0].addPoint([x, y], true, true, true);
} else {
chart.series[0].addPoint([x, y], true, false, true);
}
}
var pending = []; // pending array will contain values received for only one of the variables
function afterTemperatureReceived(x, y, tRequest){
addToChart(chartT, [x, y]);
var humidityReceived = pending.findIndex(o => Math.abs(o.tRequest - tRequest) < 100);
if(humidityReceived >= 0){ // a humidity value was received with a call time very close to this
var H = pending.splice(humidityReceived, 1)[0].H; // delete from pending and retain H value
addToChart(chartTH, [y, H]); // current y is temp, the first (x) coordinate of chartTH
}
else{ // humidity not yet received
// add temperature to pending, waiting for its humidity to be received
pending.push({T: y, tRequest});
}
}
function afterHumidityReceived(x, y, tRequest){
addToChart(chartH, [x, y]);
var temperatureReceived = pending.findIndex(o => Math.abs(o.tRequest - tRequest) < 100);
if(temperatureReceived >= 0){ // a temperature value was received with a call time very close to this
var T = pending.splice(temperatureReceived, 1)[0].T; // delete from pending and retain T value
addToChart(chartTH, [T, y]); // current y is humidity, the second (y) coordinate of chartTH
}
else{ // temperature not yet received
// add humidity to pending, waiting for its humidity to be received
pending.push({H: y, tRequest});
}
}
function mainTick(){
requestTemperature(afterTemperatureReceived);
requestHumidity(afterHumidityReceived);
}
mainTick();
setInterval(mainTick, 5000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/highcharts/10.3.2/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>
<div id="chart-temperature" style="height:20vh;min-height:350px"></div>
<div id="chart-humidity" style="height:20vh;min-height:350px"></div>
<div id="chart-temperature-humidity" style="height:20vh;min-height:350px"></div>

Highcharts with JSON data coming from microcontroler

I would like to modify the following HTML/JS code in order to fulfil the following requirements:
Select only "temp" data in my JSON file
xAxis should be "point" and not datetime
I don't want a refresh every X seconds but only when the page is refreshed.
<script>
var chartT = new Highcharts.Chart({
chart:{ renderTo : 'chart-temperature' },
title: { text: 'BME280 Temperature' },
series: [{
showInLegend: false,
data: []
}],
plotOptions: {
line: { animation: false,
dataLabels: { enabled: true }
},
series: { color: '#059e8a' }
},
xAxis: { type: 'datetime',
dateTimeLabelFormats: { second: '%H:%M:%S' }
},
yAxis: {
title: { text: 'Temperature (Celsius)' }
//title: { text: 'Temperature (Fahrenheit)' }
},
credits: { enabled: false }
});
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = (new Date()).getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chartT.series[0].data.length > 40) {
chartT.series[0].addPoint([x, y], true, true, true);
} else {
chartT.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open("GET", "/temperature", true);
xhttp.send();
}, 30000 ) ;
and my JSON looks like this:
[
{"point":184,"temp":20.5,"humidity":49.5,"weight1":0,"weight2":0},
{"point":185,"temp":20.6,"humidity":49.7,"weight1":0,"weight2":0},
{"point":186,"temp":20.6,"humidity":49.6,"weight1":0,"weight2":0}
]
right now, the command
xhttp.open("GET", "/temperature", true);
xhttp.send();
will return my whole JSON file in a string
But in the chart I only want to display the "temp" information.
You need to parse your JSON to JS object and use series.setData method. For example:
function getData() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
const data = JSON.parse(this.responseText);
const processedData = data.map(dataEl => [dataEl.point, dataEl.temp]);
chartT.series[0].setData(processedData);
}
};
xhttp.open("GET", "/temperature", true);
xhttp.send();
}
getData();
Also, please check this thread about new ways of sending requests: Parsing JSON from XmlHttpRequest.responseJSON
Live demo: http://jsfiddle.net/BlackLabel/p9gaxmju/
API Reference: https://api.highcharts.com/class-reference/Highcharts.Series#setData

Change Highcharts Graph based on two Select inputs

I have an array of data of the following format:
[["sno","day","status","data1","data2","data3","data4"],
["1","01-12-2020","success","23","66","53","34"],
["2","02-12-2020","success","12","9","8","6"],
["3","03-12-2020","success","10","11","16","13"],
["4","04-12-2020","success","34","43","54","34"],
["5","01-12-2020","fail","45","26","36","44"],
["6","02-12-2020","fail","12","15","11","13"],
["7","03-12-2020","fail","34","43","33","29"],
["8","04-12-2020","fail","23","34","31","23"]
]
to display the particular text in Highcharts I used the Following code:
var weekData = [["sno","day","status","data1","data2","data3","data4"],["1","01-12-2020","success","23","66","53","34"],["2","02-12-2020","success","12","9","8","6"],["3","03-12-2020","success","10","11","16","13"],["4","04-12-2020","success","34","43","54","34"],["5","01-12-2020","fail","45","26","36","44"],["6","02-12-2020","fail","12","15","11","13"],["7","03-12-2020","fail","34","43","33","29"],["8","04-12-2020","fail","23","34","31","23"]] ;
//console.log(weekData);
function change()
{
var valStatus = document.getElementById("statusSelect");
status = valStatus.value;
//console.log(status);
if(status == 'success')
{
const successValues = weekData.filter((x)=>x[2] === "success"); //New Cases
console.log(successValues);
return successValues;
}
else if(status == 'fail')
{
const failValues = weekData.filter((x)=>x[2] === "fail"); //New Cases
console.log(failValues)
return failValues;
}
}
function getCol(matrix, col){
var column = [];
for(var i=0; i<matrix.length; i++){
column.push(matrix[i][col]);
}
return column;
}
function chartCreate()
{
change();
const toNumbers = arr => arr.map(Number);
var getstat= change();
var day = getCol(getstat,1);
console.log(day);
var sdata1 = toNumbers(getCol(getstat,3));
console.log("data 1" ,sdata1);
var sdata2 = toNumbers(getCol(getstat,4));
console.log(sdata2);
var sdata3 = toNumbers(getCol(getstat,5));
console.log(sdata3);
var sdata4 = toNumbers(getCol(getstat,6));
console.log(sdata4);
For the full program You can check my fiddle : https://jsfiddle.net/abnitchauhan/L27n0wfs/
the problem is that when I am status select box, The Chart is not updating.
Also I feel that this code is quite lengthy when the datasets will increase overtime. is there any efficient approach to display this data on Highchart's based on the same select options.
I made an update to JS code. See if this is what you want:
var weekData = [["sno","day","status","data1","data2","data3","data4"],["1","01-12-2020","success","23","66","53","34"],["2","02-12-2020","success","12","9","8","6"],["3","03-12-2020","success","10","11","16","13"],["4","04-12-2020","success","34","43","54","34"],["5","01-12-2020","fail","45","26","36","44"],["6","02-12-2020","fail","12","15","11","13"],["7","03-12-2020","fail","34","43","33","29"],["8","04-12-2020","fail","23","34","31","23"]] ;
//console.log(weekData);
function change()
{
var valStatus = document.getElementById("statusSelect");
status = valStatus.value;
//console.log(status);
if(status == 'success')
{
const successValues = weekData.filter((x)=>x[2] === "success"); //New Cases
console.log(successValues);
return chartCreate(successValues);
}
else if(status == 'fail')
{
const failValues = weekData.filter((x)=>x[2] === "fail"); //New Cases
console.log(failValues)
return chartCreate(failValues);
}
}
function getCol(matrix, col){
var column = [];
for(var i=0; i<matrix.length; i++){
column.push(matrix[i][col]);
}
return column;
}
function chartCreate(stat)
{
const toNumbers = arr => arr.map(Number);
var getstat= stat;
var day = getCol(getstat,1);
console.log(day);
var sdata1 = toNumbers(getCol(getstat,3));
console.log("data 1" ,sdata1);
var sdata2 = toNumbers(getCol(getstat,4));
console.log(sdata2);
var sdata3 = toNumbers(getCol(getstat,5));
console.log(sdata3);
var sdata4 = toNumbers(getCol(getstat,6));
console.log(sdata4);
var options = {
chart:{
renderTo: 'chart',
defaultSeriesType: 'line'
},
title: {
text: 'dummy'
},
subtitle: {
text: ' '
},
yAxis: {
title: {
text: ' ',
//tickPointInterval: 250
},
minorTickInterval: 'auto',
// tickInterval: 4,
},
xAxis: {
labels :{
minorTickInterval: 'auto',
formatter: function(){
return day[this.value];
}
},
tickInterval: 10
},
credits: {
enabled: false
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle'
},
plotOptions: {
series: {
label: {
connectorAllowed: false
},
// pointStart: 0
}
},
tooltip: {
// split: true,
formatter: function() {
var points = this.points,
tooltipArray = ['day: <b>' + day[this.x] + '</b><br/> Value : <b>'+ this.y +'</b>']
return tooltipArray;
}
},
series: [
{
name: 'Check',
data: sdata1
}],
responsive: {
rules: [{
condition: {
maxWidth: 500
},
chartOptions: {
legend: {
layout: 'horizontal',
align: 'center',
verticalAlign: 'bottom'
}
}
}]
}
};
var chart = new Highcharts.Chart(options);
$("#dataSelect").on('change', function(){
//alert('f')
var selVal = $("#dataSelect").val();
if(selVal == 'data1' || selVal == '')
{
options.series = [{name: 'Data', data: sdata1}];
options.yAxis = [{tickInterval:undefined, minorTickInterval: 'auto'}];
}
else if(selVal == 'data2')
{
options.series = [{name: 'Data', data: sdata2}]
}
else if(selVal == 'data3')
{
options.series = [{name: 'Data', data: sdata3}];
options.yAxis = [{tickInterval:undefined, minorTickInterval: 'auto'}];
}
else if(selVal == 'data4')
{
options.series = [{name: 'Data', data: sdata4}];
options.yAxis = [{tickInterval:undefined, minorTickInterval: 'auto'}];
}
var chart = new Highcharts.Chart(options);
});
}
change();
Your code looks very complex and does not fully work. In this case, I will suggest using the series setData method mixed with the change event listener. My example is a bit simplified, but I think it might be the right way.
document.getElementById('dataSelect').addEventListener('change', () => {
const selectorValue = document.getElementById('dataSelect').value
chart.series[0].setData(data[selectorValue])
});
API: https://api.highcharts.com/class-reference/Highcharts.Series#setData
Demo: https://jsfiddle.net/BlackLabel/nfz0a9bm/

Is it possible to show the chart if the value of array bracket is null or empty in the HighChart

I have problem regarding on my HighChart because when my json response is null or empty the chart is not shown, if the response has a value the bar is show. so the question is it possible in the highchart if the value of json response is null?
My Column Chart show the output like this:
Response:
My HighChart Function:
categories = [],
seriesNames = ['MR', 'MR_HIT', 'MR_HIT_PERCENTAGE'],
series = [];
$.getJSON('ajax/ams_sla_report_chart.php', function(data,name){
data.forEach(function(arr) {
arr.forEach(function(el, i) {
if (i === 0) {
categories.push(el);
} else if (series[i - 1]) {
series[i - 1].data.push(el);
} else {
series.push({
name: seriesNames[i - 1],
data: [el]
});
}
});
});
var chart = new Highcharts.Chart({
chart: {
renderTo: 'containers',
type: 'column',
inverted: false
},
legend: {
layout: 'horizontal',
align: 'right',
verticalAlign: 'middle'
},
xAxis: {
categories: categories
},
plotOptions: {
column: {
minPointLength: 3
}
},
title: {
text: 'Priority Based on SLA'
},
series:series
});
// chart.series[0].name="SOLVED MR";
// chart.series[1].name="TOTAL MR HIT";
// chart.series[2].name="TOTAL MR HIT PERCENTAGE";
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_eng input').on('input change', function () {
chart.options.chart.options3d[this.id] = parseFloat(this.value);
showValues();
chart.redraw(false);
});
showValues();
});
It will not be possible to draw chart if series is empty. You can add an if clause and draw chart only if series have data. Else show a different message
$.getJSON('ajax/ams_sla_report_chart.php', function(data, name) {
data.forEach(function(arr) {
arr.forEach(function(el, i) {
if (i === 0) {
categories.push(el);
} else if (series[i - 1]) {
series[i - 1].data.push(el);
} else {
series.push({
name: seriesNames[i - 1],
data: [el]
});
}
});
});
if (series.length !== 0) { // show chart only if series has data
var chart = new Highcharts.Chart({
chart: {
renderTo: 'containers',
type: 'column',
inverted: false
},
legend: {
layout: 'horizontal',
align: 'right',
verticalAlign: 'middle'
},
xAxis: {
categories: categories
},
plotOptions: {
column: {
minPointLength: 3
}
},
title: {
text: 'Priority Based on SLA'
},
series: series
});
// chart.series[0].name="SOLVED MR";
// chart.series[1].name="TOTAL MR HIT";
// chart.series[2].name="TOTAL MR HIT PERCENTAGE";
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_eng input').on('input change', function() {
chart.options.chart.options3d[this.id] = parseFloat(this.value);
showValues();
chart.redraw(false);
});
showValues();
} // end of if
else {
// add a code to ask user to slet user know that chart cannot be drawn
}
});
You can the no-data-to-display module to show a message on a chart when there is no data:
lang: {
noData: "no-data-to-display"
},
noData: {
...
}
Live demo: https://jsfiddle.net/BlackLabel/8acxywjv/
API Reference: https://api.highcharts.com/highcharts/noData

How to add data tables to dynamically generated highcharts

I want to add data tables to Charts.
I tried the implementation shown here: http://jsfiddle.net/highcharts/z9zXM/
but it didnt work for me.
I suspect its because how I instantiate highcharts.
in the example above the chart is generated by instantiating the Highcharts object.
my code:
// data from an ajax call
$.each(data, function(indicator, questions) {
indicator_type = "";
$.each(questions, function(question, value) {
dataChartType = "column";
series = [];
categories = [];
category_totals = {};
if(value.programs == null) {
return true;
}
$.each(value.programs, function(program, body) {
total = 0;
values = [];
$.each(body, function(j, k) {
if (categories.indexOf(j) == -1) {
categories.push(j);
category_totals[j] = 0;
}
if(k != 0) {
values.push(k);
} else {
values.push(null);
}
category_totals[j] += parseInt(k, 10);
total += k;
});
series.push({
data: values,
total: total,
name: program //question
});
}); // eo each program
var chartDiv = document.createElement('div');
chartDiv.className = "chart";
$('.charts_wrap').append(chartDiv);
$(chartDiv).highcharts({
events: {
load: Highcharts.drawTable
},
chart: {
type: dataChartType
},
xAxis: {
categories: categories
},
legend: {
layout: 'vertical',
backgroundColor: '#FFFFFF',
align: 'right',
verticalAlign: 'top',
y: 60,
x: -60
},
tooltip: {
formatter: function () {
return '<strong>' + this.series.name + '</strong><br/>' + this.x + ': ' + this.y;
}
},
plotOptions: {
line: {
connectNulls: true
},
column: {
stacking: 'normal',
dataLabels: {
enabled: false,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white',
style: {
textShadow: '0 0 3px w'
}
}
}
},
series: series,
title:{ text: indicator },
subtitle:{ text: question }
});
}); // EO each question
}); // eo each indicator
When instantiating highcharts like this:
$("#container").highcharts({ ...
The events option needs to be included inside the charts option:
$("#container").highcharts({
chart: {
type: 'column',
events: {
load: Highcharts.drawTable
},
},
...

Categories

Resources