How to update mulitple series in Highcharts simultaneously - json

I'm using Highcharts to graph multiple series on a single chart. The series data is read from a file containing the data in JSON format. The file will get updated with new data every few seconds and I've a function to re-read the file.
Here's the data in the file:
[{"name": "series1", "data": [[1,109],[2,313],[3,192]]},{"name": "series2", "data": [[1,111],[2,112],[3,777]]}]
The code I've got is:
//Read JSON data from a file
$(function () {
function getSeriesData(file) {
var data = null;
$.ajax({
async: false,
cache: false,
url: file,
method: 'GET',
dataType: 'json',
success: function(datasets){
data = datasets;
},
error: function(error,text,http){
alert("Error retrieving " + url + ".");
}
});
return data;
}
var graphData = getSeriesData("seriesData.json");
var graphOptions = {
chart: {
type: 'line',
renderTo: "container",
},
series: graphData
};
var graph = new Highcharts.Chart(graphOptions);
var updateInterval = 1000 * 5; // 5 seconds
function update() {
//Need to refresh series data here.
//Something like:
graph.series = getSeriesData("series.json");
graph.redraw();
setTimeout(update, updateInterval);
}
update();});
Looking at the documentation there doesn't seem to be a way to set all the series data again at the same time using my getSeriesData function to reread the file. Most of the examples here and elsewhere have ways to set the data for individual series by going through the series[] array. But thats not what I'm looking for. Maybe I'll have to redo the code to do it that way but thought I'd check here first in the hope that there's an easier way! Thanks in advance.

I can't see a way to do all series with one call. I can see two options.
If the number of series is fixed, you can iterate over them calling series.setData with the redraw option set to false, and then call redraw().
If the number of series may change, you will have to iterate over the chart.series calling remove, and then iterate over your series array calling chart.addSeries.

Related

Using data in html from an API response

As a starter in html world, i would like to know and start using simple APIs to insert into my blog posts.
I tried to include as html values some simple API like: https://bitcoinfees.earn.com/api/v1/fees/recommended and I used examples given here: Display Json data in HTML table using javascript and some others more like: http://jsfiddle.net/sEwM6/258/
$.ajax({
url: '/echo/json/', //Change this path to your JSON file.
type: "post",
dataType: "json",
//Remove the "data" attribute, relevant to this example, but isn't necessary in deployment.
data: {
json: JSON.stringify([
{
id: 1,
firstName: "Peter",
lastName: "Jhons"},
{
id: 2,
firstName: "David",
lastName: "Bowie"}
]),
delay: 3
},
success: function(data, textStatus, jqXHR) {
drawTable(data);
}
});
function drawTable(data) {
var rows = [];
for (var i = 0; i < data.length; i++) {
rows.push(drawRow(data[i]));
}
$("#personDataTable").append(rows);
}
function drawRow(rowData) {
var row = $("<tr />")
row.append($("<td>" + rowData.id + "</td>"));
row.append($("<td>" + rowData.firstName + "</td>"));
row.append($("<td>" + rowData.lastName + "</td>"));
return row;
}
but the result is always blank.
Please, can you give me some hint to can use that API and insert that numbers values for "fastestFee","halfHourFee","hourFee" as html values?
Thank you all!
Welcome to the html world. You are certainly right in assuming that data from APIs is a great way to make your websites more dynamic.
There is an example on W3 Schools on how to handle a http request. I think this is a good place to start https://www.w3schools.com/xml/xml_http.asp. You create a http object that does some sort of data fetching. In this example it is done with the xhttp.send(). At the same time you have a listener that monitors if the onreadystatechange property of the xhttp has changed. And if that change is status 200 (success) then perform some actions.
Here is my JSfiddle with example from your API
http://jsfiddle.net/zvqr6cxp/
Typically these actions would be to structure the returned data and then do something with the data, like show them in a table.
The example shows the native html xhttp object in use with an event listener. Typically as you learn more about this you would probably start using a framework such as jquery or Angular that can handle http requests smoother, keyword here is callback functions.
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
//In this example, I used your API link..first I would do is turn the JSON into a JS object
myObject = JSON.parse(xhttp.responseText)
document.getElementById("fast").innerHTML = myObject.fastestFee
document.getElementById("half").innerHTML = myObject.halfHourFee
document.getElementById("hour").innerHTML = myObject.hourFee
}
};
xhttp.open("GET", "https://bitcoinfees.earn.com/api/v1/fees/recommended", true);
xhttp.send();

Displaying JSON data into a pie chart using chart.js

my first time using chart.js and am running into a small bug that I can't seem to work around it. Below is my code, however, its just displaying the labels but not rendering the pie chart itself.
Am following samples from the chart.js documentation here http://www.chartjs.org/docs/#doughnut-pie-chart-example-usage
Your help will be appreciated.
<canvas id="myChart" width="200" height="200"></canvas>
$(document).ready(function () {
/*
-> #47A508 = green (wins)
-> #ff6a00 = orange (losses)
-> #ffd800 = yellow (draws)
*/
var DataArray = [];
var ctx = document.getElementById("myChart");
$.ajax({
url: 'http://api.football-data.org/v1/competitions/426/leagueTable',
dataType: 'json',
type: 'GET',
}).done(function (result) {
$.each(result.standing, function () {
var name = "Manchester United FC";
if (this.teamName == name) {
DataArray.push([this.wins, this.losses, this.draws]);
}
});
var myChart = new Chart(ctx, {
type: 'pie',
data: {
label: 'Manchester United Current Form',
labels: [
"Wins",
"Losses",
"Draws"
],
datasets: [
{
data: DataArray,
backgroundColor: [
"#47A508",
"#ff6a00",
"#ffd800"
],
hoverBackgroundColor: [
"#FF6384",
"#36A2EB",
"#FFCE56"
]
}]
},
options: { responsive: true }
});
});
}
maybe it is because of the jquery each, it fills DataArray async and the array is not ready, when you want to use it as chart data.
Change the $.each to a simple js for loop
for(var i = 0; i < result.standing; i++){
var name = "Manchester United FC";
var team = result.standing[i];
if (team.teamName == name) {
DataArray.push(team.wins, team.losses, team.draws);
}
}
try callbacks for you ajax or do the below (which is a dirty solution):
$.ajax({
url: 'http://api.football-data.org/v1/competitions/426/leagueTable',
dataType: 'json',
cache: false, //add this
async: false, //add this
type: 'GET',
Also
the result of your ajax could be returned using the below code instead of using an array.
jQuery.parseJSON(result);
The issue lies in your DataArray. The way it is implemented is is an array with a single entry. Which is another array itself.
[[<wins>, <losses>, <draws>]]
instead of
[<wins>, <losses>, <draws>]
That is because you instantiate an array and then push into it an array object.
To fix this try using the following function:
(...)
$.each(result.standing, function () {
var name = "Manchester United FC";
if (this.teamName == name) {
DataArray = ([this.wins, this.losses, this.draws]);
console.log("This team name");
}
});
(...)
I got this solved, well sadly, with no magic at all to brag about. There was nothing wrong with the code initially, however, it was a problem with the DOM rendering performance. Thank you #alwaysVBNET and #Aniko Litvanyi for your inputs as well.
This link helped me out, hopefully it does to someone out there.

update jqPlot with json data (flicker)

So I've put this together from a bunch of examples around the internet. I'm pulling data from a text file and plotting it with jqPlot. I'm then recalling a function to continually update the plot from the file:
<div id="chart1" style="height:300px; width:500px;"></div>
<script class="code" type="text/javascript">
// Our ajax data renderer which here retrieves a text file.
// it could contact any source and pull data, however.
// The options argument isn't used in this renderer.
var ajaxDataRenderer = function(url, plot, options) {
var ret = null;
$.ajax({
// have to use synchronous here, else the function
// will return before the data is fetched
async: false,
url: url,
dataType:"json",
success: function(data) {
ret = data;
}
});
return ret;
};
// The url for our json data
var jsonurl = "./jsondata.txt";
// passing in the url string as the jqPlot data argument is a handy
// shortcut for our renderer. You could also have used the
// "dataRendererOptions" option to pass in the url.
var plot1;
$(document).ready(function(){
plot1 = $.jqplot('chart1', jsonurl,{
title: "MY GRAPH",
dataRenderer: ajaxDataRenderer,
dataRendererOptions: {
unusedOptionalUrl: jsonurl
}
});
ConstantPlotter();
});
function ConstantPlotter() {
plot1.destroy();
plot1 = $.jqplot('chart1', jsonurl,{
title: "MY GRAPH",
dataRenderer: ajaxDataRenderer,
dataRendererOptions: {
unusedOptionalUrl: jsonurl
}
});
setTimeout(ConstantPlotter,100)
}
</script>
It works fine, but the plot flickers badly since it's being destroyed and recreated every time. The problem is that when I try to replace the 'destroy and plot' code with
plot1 = $.jqplot('chart1', jsonurl,{
title: "MY GRAPH",
dataRenderer: ajaxDataRenderer,
dataRendererOptions: {
unusedOptionalUrl: jsonurl
}
}).replot();
it works beautifully but I get a terrible memory leak.
Does anyone know a way to constantly update this plot from the file without having the terrible flicker? Thanks!

How to get multiple data series into Highcharts

The following code works:
var options1 = {
chart: {
renderTo: 'container1'
},
series: [{}]
};
$.getJSON('tokyo.jsn', function(data){
options1.series[0].data = data;
var chart = new Highcharts.Chart(options1);
});
I want to be able to add a number of data series, so I am trying to take the reference to ‘new Highcharts’ out of the getJSON, but I don't seem to get it right. This following code does not work:
$.getJSON('tokyo.jsn', function(data){
options1.series[0].data = data;
});
var chart = new Highcharts.Chart(options1);
I have also tried tackling it a different way but again the following code does not work:
var chart1 = new Highcharts.Chart({
chart: {
renderTo: 'container1'
},
series: [{}]
});
$.getJSON('tokyo.jsn', function(data){
chart1.series[0].data = data;
});
Can anyone point me in the correct direction. I need to be able to support multiple data series by doing a second getJSON call like the following:
$.getJSON('sydney.jsn', function(data){
options1.series[1].data = data;
});
The JSON code I'm using is as follows:
[ 7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6 ]
Thanks
$.getJSON is an asynchronous request. Once you receive the data, then you can pass it to Highcharts, thus you have to call that code from within the callback function of $.getJSON().
Try this, use a helper function to process your data and draw the chart, see drawChart() below:
var options1 = {
chart: {
renderTo: 'container1'
},
series: []
};
var drawChart = function(data, name) {
// 'series' is an array of objects with keys:
// - 'name' (string)
// - 'data' (array)
var newSeriesData = {
name: name,
data: data
};
// Add the new data to the series array
options1.series.push(newSeriesData);
// If you want to remove old series data, you can do that here too
// Render the chart
var chart = new Highcharts.Chart(options1);
};
$.getJSON('tokyo.jsn', function(data){
drawChart(data, 'Tokyo');
});
$.getJSON('sydney.jsn', function(data){
drawChart(data, 'Sydney');
});
See fiddle: http://jsfiddle.net/amyamy86/pUM7s/
You can use solution used by Highcharts in that example: http://www.highcharts.com/stock/demo/compare
Or first create empty chart, without any series, and then use addSeries() function in each callback, see: http://api.highcharts.com/highcharts#Chart.addSeries()

Update chart data in Dojo

I have the below function which reads JSON data and puts it on a chart. I would like to automatically update the chart data every say 10 seconds.
I have looked at dojo/timing and chart.updateSeries and I believe the combination of the two would do the trick but I'm not sure how I can implement this. Any help would be greatly appreciated.
function(xhr, json, arrayUtil, number, Chart, theme) {
var def = xhr.get({
url: "cpuusage.json",
handleAs: "json"
});
def.then(function(res){
var chartData = [];
arrayUtil.forEach(res.chart, function(chart){
chartData[chart.x] = number.parse(chart.y);
});
//Draw chart
var chart = new Chart("chartNode2");
chart.setTheme(theme);
chart.addPlot("default", {
type: "Columns",
markers: true,
gap: 5
});
chart.addAxis("x");
chart.addAxis("y", { vertical: true, fixLower: "major", fixUpper: "major" });
chart.addSeries("Monthly Sales",chartData);
chart.render();
}, function(err){
console.error("Failed to load JSON data");
});
}
Try something like that:
var interval = setInterval(function(){
// let's get new data
xhr.get({
url: "cpuusage.json",
handleAs: "json"
}).then(function(res){
// data prep step - just like before
var chartData = [];
arrayUtil.forEach(res.chart, function(chart){
chartData[chart.x] = number.parse(chart.y);
});
// update chart (it was created before)
chart.updateSeries("Monthly Sales", chartData);
chart.render();
}, function(err){
console.error("Failed to load updated JSON data");
});
}, 10000); // 10s
...
// when we want to cancel updates
clearInterval(interval);
Sorry, I didn't use dojo/timing, I don't see much reason for it here, and prefer simple ways to do simple things.